什么是反射?
Java中的反射是指在程序运行的时候,通过Class对象拿到类中构造方法,成员方法,成员变量,并且操作构造方法,成员方法,成员变量
反射的应用场景?
1.各种IDE(集成开发工具)
2.各种框架
反射的好处:
1.可以在程序运行过程中,操作这些对象。
2.可以解耦,提高程序的可扩展性。
3.灵活,修改文件,不需要修改代码(降低代码的耦合性)
4.后面写的文件可以直接加进来使用(提高程序的扩展性)
小结
1.什么是反射?
Java中的反射是指在程序运行的时候,通过Class对象拿到类中构造方法,成员方法,成员变量,并且操作构造方法,成员方法,成员变量
三种获取Class对象的方式
1.类名.class
2.对象.getClass()
3.Class.forName(类全名);
1 ,// 1.类名.class
Class cls1 = Employee.class;
System.out.println(cls1); // class com.itheima.bean.Employee
2,
Employee e = new Employee();
Class cls2 = e.getClass();
System.out.println(cls2); // class com.itheima.bean.Employee
3
Class cls3 = Class.forName("com.itheima.bean.Employee");
System.out.println(cls3); // class com.itheima.bean.Employee 最常用的就是这种
Class类中的方法:
getName: 获取类全名 com.itheima.bean.Employee
getSimpleName: 获取类名 Employee
Class cls = Class.forName("com.itheima.bean.Employee");
System.out.println(cls.getName()); // com.itheima.bean.Employee
System.out.println(cls.getSimpleName()); // Employee
Constructor类作用:
Constructor表示类中的构造方法,必须先获得Class对象 ,然后就通过Class对象,可以指定取哪一个构造器的方法,不管权限
Constructors 必须先获得Class对象 ,然后就通过Class对象 可以获取所有的构造器的方法
Class cls = Class.forName("com.itheima.bean.Employee");
Constructor c1 = cls.getConstructor();
Object o = c1.newInstance("凤凰街",18); //创建实例 / 对象
如何得到声明的Constructor?
getDeclaredConstructors: 获取所有声明的Constructor,全部的方法,包括构造方法
getDeclaredConstructor: 获取一个声明的Constructor,获取随意一个方法,包括构造方法
Class cla=Class.forName("com.itheima.bean.Employee");
Constructor c1 = cla.getDeclaredConstructor(String.class);
c1.setAccessible(true); //暴力反射
Employee o = (Employee) c1.newInstance("我爱你"); //创建实例
System.out.println(o);
------------------------------------------------------
Class cls = Class.forName("com.itheima.bean.Employee");
Employee e1 = (Employee) cls.newInstance(); // 调用Employee类的无参构造创建对象,只能创建无参构造器
Constructor c2 = cls.getConstructor();
Employee e2 = (Employee) c2.newInstance(); // 调用Employee类的无参构造创建对象或有参构造创建对象
Employee e3 = new Employee();
getMethods: 获取所有的public的方法(包括父类的)
getMethod: 获取一个的public的方法
getDeclaredMethods: 获取所有声明的方法(只包含本类)
getDeclaredMethod: 获取一个声明的方法
invoke(Object obj, Object ... objs)
// 1.获取Class对象
Class cls = Class.forName("com.itheima.bean.Employee");
Employee e1 = (Employee) cls.newInstance();
// 2.通过Class对象获取Method
// getMethods: 获取所有的public的方法(包括父类的)
// Method[] methods = cls.getMethods();
// for (Method m : methods) {
// System.out.println(m);
// }
// getMethod: 获取一个的public的方法
Method m1 = cls.getMethod("setName", String.class);
System.out.println(m1);
// 对象.方法名(); 使用对象调用方
// 使用e1对象调用m1(setName)方法,传入的参数是"苍老师".
m1.invoke(e1, "苍老师");
System.out.println(e1); // Employee{name='苍老师', age=0}
// getDeclaredMethods: 获取所有声明的方法(只包含本类)
// Method[] methods = cls.getDeclaredMethods();
// for (Method m : methods) {
// System.out.println(m);
// }
// getDeclaredMethod: 获取一个声明的方法
Method m2 = cls.getDeclaredMethod("sleep", int.class);
System.out.println(m2);
m2.setAccessible(true);
Object re = m2.invoke(e1, 10);
System.out.println("返回值: " + re);
Field的操作:
赋值,取值
引用数据类型:
get();
set();
基本数据类型:
getXxx(); getDouble(),getInt()
setXxx(); setDouble(),setInt()
getFields: 获取所有public的成员变量
getField: 获取一个publicd的成员变量
getDeclaredFields: 获取所有声明的成员变量
getDeclaredField: 获取一个声明的成员变量
注解:
注释:对程序进行解释说明的文字。注释给程序员看的
什么是注解?
给程序使用的,注解可以给类携带额外的信息
常见注解:
1.@author:用来标识作者名。
2.@version:用于标识对象的版本号。
3.@since: 从哪个版本开始
4.@Override :检测是否是重写方法
注解的作用:
编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
代码分析:通过代码里标识的注解对代码进行分析【使用反射】
自定义注解的格式? 注解的属性类型:
1.八种基本数据类型
注意:自定义的类型不行 2.String,枚举,注解可以
3.以上类型的一维数组[]
@interface {
// 属性 数据类型 属性名();
}
使用自定义注解格式:
@注解名(属性名1=属性值1, 属性名2=属性值2,...)
注意:需要保证注解的每个属性都有值.
public @interface MyAnno2 {
// 属性
String[] authors(); // 作者
double price() default 0.99; // 价格
String name(); // 书名
}
@MyAnno2(name="西游记", price=9.9, authors={"吴承恩", "丘处机", "李天一"})
public class Demo102 {
@MyAnno2(name = "东游记", authors = {"黄思洁"})
public static void main(String[] args) {
}
}
当注解中只有一个属性,并且属性名是value,在使用注解时,可以省略属性名
两种写法
@MyAnno3(value = "aaa") 第一种
public class Demo11 {
@MyAnno3("aaa") 第二种
public static void main(String[] args) {
}
}
1.什么是元注解?
修饰注解的注解
2.@Target元注解
@Target:限制注解能放在什么地方(默认是任何地方都能放)
3.@Retention元注解
限制注解能活到什么时候 (默认是CLASS阶段)
SOURCE CLASS RUNTIME
源代码阶段
.java -> .class -> 运行
//@Target(ElementType.TYPE) // 能放在类或者接口上
//@Target(ElementType.CONSTRUCTOR) // 能放在构造方法上
//@Target(ElementType.FIELD) // 能放在成员变量上
//@Target(ElementType.METHOD) // 能放在方法上
//@Target(ElementType.LOCAL_VARIABLE) // 能放在局部变量上
//@Target({ElementType.TYPE, ElementType.CONSTRUCTOR}) // 能放在局部变量上
//@Retention(RetentionPolicy.SOURCE) // 能存活到源代码阶段
//@Retention(RetentionPolicy.CLASS) // 能存活到class阶段
@Retention(RetentionPolicy.RUNTIME) // 能存活到运行时阶段
public class Book {
@MyAnno4
@BookAnno(name = "西游记", price = 99, authors = {"吴承恩", "丘处机", "李春芳"})
public void sale(String name, double price, String[] authors) {
}
}
public class Demo13 {
// 我们点左边绿色的三角形,程序就运行起来的.
public static void main(String[] args) throws Exception {
// 1.获取Class对象
Class cls = Class.forName("com.itheima.demo13注解解析.Book");
// 2.获取Method
Method method = cls.getMethod("sale",String.class,double.class,String[].class);
// 3.通过Method获取注解
// Annotation[] annotations = method.getAnnotations();
// for (Annotation a : annotations) {
// System.out.println(a);
// }
// 在获取一个注解的时候最好先判断方法上是否有这个注解
boolean b = method.isAnnotationPresent(BookAnno.class);
System.out.println(b);
if (b) {
BookAnno an = method.getAnnotation(BookAnno.class);
System.out.println(an.name() + " :: " + an.price() + " :: " + Arrays.toString(an.authors()));
}
}
}
通过反射可以拿到所对应的值