Java学习-注解和反射
注解
java.Annotation
Annotation的作用:可以呗其他程序读取
Annotation的格式
注解是:@注释名 在代码中存在,还可以添加一些参数
@SuppressWarnings(values="unchecked")
通过反射,可以访问数据。
内置注解
@override
:定义在java.lang.Override中,此注解只适用于修饰方法,标识一个方法声明打算重写父类的另一个方法。
@Deprecated
:定义在java.lang.Deprecated中,此方法用于修饰方法,类,属性。表示废弃元素
@SuppressWarings
:定义在java.lang.SuppressWarings中,用来抑制编译时的警告信息。
- 此方法需要传入参数。
public class Demo01 extends Object {
//重写的注解
@Override
public String toString() {
return super.toString();
}
//不推荐使用的注解,但是可以使用
@Deprecated
public static void test() {
System.out.println("Deprecated");
}
@SuppressWarnings("all")
public static void test2() {
ArrayList arrayList = new ArrayList();
}
public static void main(String[] args) {
test();
}
}
元注解
元注解就是负责注解其他的注解,Java定义了四个标准的meta-annotation类型,他们用来提供对其他annotation类型操作说明
可以从java.lang.annotation中找到(@Target,@Retention,@Docimented,@Inherited)
@Target:用于描述注解的使用范围({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention:标识需要在什么级别保存该注解信息,用于描述注解的生命周期(SOURCE<CLASS<RENTIME)
@Docimented:说明注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
自定义注解
使用@interface自定义注解
格式
public @interface MyAnnotation
{
}
public class Demo02 {
//注解可以显示的复制,如果没有默认值,就一定要注解赋值
@MyAnnotation(name = "nice",schools = {"1234","2314"})
public void test(){}
@MyAnnotation2("sdf")
public void test2(){}
}
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value =RetentionPolicy.RUNTIME)
@interface MyAnnotation
{
//注解的参数:参数类型 参数名();
String name() default "";
int age() default 0;
int id() default -1;//代表不存在。
String[] schools() default {"erq","asds"};
}
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(value =RetentionPolicy.RUNTIME)
@interface MyAnnotation2
{
//注解的参数:参数类型 参数名();
String value() default "";
}
反射
java.Reflection
反射机制允许程序在执行期间借助Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性级方法
Class c= Class.forName("java.lang.String")
获得反射对象
public class Demo03 {
public static void main(String[] args) throws ClassNotFoundException {
//通过反射获取类的class对象
Class c1 = Class.forName("com.darker.demo01.User");
Class c2 = Class.forName("com.darker.demo01.User");
Class c3 = Class.forName("com.darker.demo01.User");
//一个类在内存中只有一个Class对象
//一个类被加载后,类的整个结构都会被装在Class对象中
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
}
}
Class对象
方法名 | 功能说明 |
---|---|
static ClassforName(String name) | 返回指定类名name的Class对象 |
Object newInstance() | 调用缺省构造函数,返回Class对象的一个实例 |
getName() | 返回此Class对象锁标识的实体(类、接口、数组类或void)的名称 |
Class getSuperClass() | 返回此Class对象的父类的Class对象 |
Class[] getinterfaces() | 获取此Class对象的接口 |
ClassLoader getClassLoader() | 返回该类的类加载器 |
Constructor[] getConstructors() | 返回一个包含某些Constructor对象的数组 |
Method getMethod(String name,Class...T) | 返回一个Method对象,此对象的类型类paramaType |
Field[] GetDeclaredFields() | 返回Field对象的一个数组 |
获取Class对象
public class Demo04 {
public static void main(String[] args) throws ClassNotFoundException {
Person person = new Student();
System.out.println("这个人是"+person.name);
//方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());
//方式二:forname获得
Class c2 = Class.forName("com.darker.demo01.Student");
System.out.println(c2.hashCode());
//方式三:通过类名.class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());
//方式四,基本内置类型的包装类都有一个type属性
Class c4 = Integer.TYPE;
System.out.println(c4.hashCode());
//获得父类类型
Class c5 = c1.getSuperclass();
System.out.println(c5);
}
}
class Person{
public String name;
public Person() {
}
Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person
{
public Student() {
this.name = "学生";
}
}
class Teacher extends Person
{
public Teacher() {
this.name = "老师";
}
}
哪些类型有Class对象
class:外部类,成员内部类,静态内部类,局部内部类,局部内部类,匿名内部类。
interface:接口
[]:数组
enum:枚举
annotation:注解@interface
primitive type:基本数据类型
void
class内存分析
public class Demo05 {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
/*
1.加载到内存,会产生一个类的对应的Class对象
2.链接,链接后m=0
3.初始化
<cinit>(){
System.out.println("A类静态代码块初始化");
m = 300;
m = 100;
}
*/
}
}
class A{
static {
System.out.println("A类静态代码块初始化");
m=300;
}
static int m = 100;
public A()
{
System.out.println("A类的无参构造初始化");
}
}
打印结果:
A类静态代码块初始化
A类的无参构造初始化
100
类的初始化
类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类
- new一个类对象
- 调用静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法惊醒反射调用
- 当初始化一个类,如果其父类没有初始化,咋会初始化它的父类
类的被动引用(一定不会发生类的初始化)
- 通过数组定义类引用
- 引用常量触发此类的初始化(常量在链接阶段就存入调用类的常量池中)
- 当访问一个静态域,只有真正声明这个域的类才会被初始化。如:通过子类调用父类的静态变量。
类加载器
引导类加载器
扩展类加载器 ExtClassLoader 负责jre/lib/ext目录下的jar包或者-D java.ext.dirs指定目录下的jar包装入工作库
系统类加载器 AppClassLoader 负责java -classpath或-D java.class.path所指的目录下的类与jar包装如工作库,是最常用的加载器
public class Demo06 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类加载器的父类加载器--》扩展类接在其
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类加载器的父类加载器--》根加载器(c/C++)
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
ClassLoader classLoader = Class.forName("com.darker.demo01.Demo06").getClassLoader();
System.out.println(classLoader);
//如何获取系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
}
}
获取类的信息
public class Demo07 {
public static void main(String[] args) throws ClassNotFoundException {
Class aClass = Class.forName("com.darker.demo01.User");
//获得类的名字
System.out.println("获得类的名字");
//获得包名+类名
System.out.println(aClass.getName());
//获得类名
System.out.println(aClass.getSimpleName());
//获得类的属性
System.out.println("获得类的属性");
//只能找到public属性
Field[] fields = aClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
//能找到全部属性
Field[] declaredFields = aClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
//获得类的方法
System.out.println("获得类的方法");
//获得本类和父类的所有public方法
Method[] methods = aClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("=========================");
//获得本类所有方法
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
}
通过反射操作类
public class Demo08 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException {
Class c1 = Class.forName("com.darker.demo01.User");
//构造一个对象
User user1 = (User) c1.newInstance();
System.out.println(user1);
//通过构造器创建对象
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
Object user2 = constructor.newInstance("Darker", 1, 22);
System.out.println(user2);
//通过反射调用普通方法
User user3 = (User) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke激活。(对象,“方法值”)
setName.invoke(user3, "darkerJO");
System.out.println(user3);
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全监测,属性或方法的setAccessible(true)
name.setAccessible(true);
name.set(user4, "DarkerGuo");
System.out.println(user4);
}
}