第十天:Java反射
反射
反射就是:加载类,并编写代码获取类中的成员变量,方法,构造器等。
注意:反射,注解,动态代理就是用来学习框架做框架的,在平时业务开发需求上很少用到。
1 反射学什么?
2 获取Class对象的三种方式
2.1 通过类名.class获取
Class c1=类名.class
Class c1=Student.class;
System.out.println(c1.getName());//全类名=包名+类名
System.out.println(c1.getSimpleName());//简名
2.2 通过Class提供的方法forName()
Class.forName(“填自己想获得的类的全类名”)
Class c2=Class.forName("com.xie.Student");
2.3 通过对象提供的方法
Class c3=对象.getClass()
Student student=new Student();
Class c3=student.getClass();
3 获取类的构造器
3.1 getConstructors()
获取所有公共构造函数(在开发中一般不会用这个)
Class c1=Cat.class;
Constructor[] cons=c1.getConstructors();
3.2 getDeclaredConstructors()
获取所有构造函数,可以是公共、私有或受保护的构造函数。(开发中推荐使用)
Class c2=Cat.class;
Constructor[] cons=c2.getDeclaredConstructors();
3.3 getConstructor(Class<?>… parameterTypes)
获取指定参数类型的公共构造函数
Class c1=Cat.class;
Constructor constructor=c1.getConstructor();
3.4 getDeclaredConstructor(Class<?>… parameterTypes)
获取指定参数类型的构造函数,可以是公共、私有或受保护的构造函数(推荐)
Class c2=Cat.class;
Constructor constructor=c2.getDeclaredConstructor(String.class,int.class);
4 获取类的构造器的作用
作用:初始化对象并返回
4.1 初始化对象newInstance(参数)
调用此构造器对象表示的构造器,并传入参数,完成对象初始化,并返回。(不能调用私有的构造器)
Class c1=Cat.class;
Constructor constructor=c1.getDeclaredConstructor(String.class,int.class) ;
Cat cat=(Cat)constructor.newInstance("小橘猫",2);
4.2 setAccessible(true)
绕过私有成员的访问限制,访问/修改私有字段、方法或构造方法。
Class c1=Cat.class;
Constructor constructor=c1.getDeclaredConstructor();
constructor.setAccessible(true);
//表示禁止检查访问控制,因为Cat的无参构造方法是私有的,newInstance()
//无法访问,因此使用setAccessible(true),后续newInstance()
//才可以调用
Cat cat=(Cat)constructor.newInstance();
System.out.println(cat);
5 获取类的成员变量
5.1 getFields()
获取所有 public 字段(包括继承的)
Class c1=Cat.class;
Field[] fields=c1.getFields();
for(Field f:fields){System.out.println(f.getName()+"-->"+f.getType());
}
5.2 getDeclaredFields()
获取所有字段(包括 private,但不包括继承的)
推荐用这个
Class c1=Cat.class;
Field[] fields=c1.getDeclaredFields();
for(Field f:fields){System.out.println(f.getName()+"-->"+f.getType());
}
5. 3 getField(“参数”)
获取指定名称的 public 字段(包括继承的)
Class c1=Student .class;
Field f1=c1.getDeclaredField("name");
5.4 getDeclaredField(“参数”)
获取指定名称的字段(包括 private,但不包括继承的)
推荐用这个
Class c1=Cat.class;
Field f=c1.getDeclaredField("age");
System.out.println(f.getType());
6 使用成员变量
6.1 void set(Object obj, Object value)
修改指定对象的字段值。
Class c=Cat.class;
Field cName=c.getDeclaredField("name");
Field cAge=c.getDeclaredField("age");
Constructor constructor =c.getDeclaredConstructor();
//newInstance()无法调用私有构造器
Cat cat = (Cat) constructor.newInstance();
cName.setAccessible(true);
cName.set(cat, "加菲猫") ;
cAge.setAccessible(true) ;
cAge.set(cat, 18);
6.2 Object get(Object obj)
取变量的值
int age=(int) cAge.get(cat);
6.3 setAccessible(true)
设置为true ,表示禁止检查访问控制(暴力反射)
cAge.setAccessible(true) ;
7 获取类的成员方法
7.1 getMethods()
获得该类所有方法(只获取带有public修饰的方法)
Class dog=Dog.class;
//获取类的全部成员方法
Method[] methods=dog.getMethods();
7.2 getDeclaredMethods()
获得该类所有方法
Class dog=Dog.class;
//获取类的全部成员方法
Method[] methods=dog.getDeclaredMethods();
7.3 getDeclaredMethod(String name, Class…<?> parameterTypes)
获得该类某个方法
7.3.1 无参的
Class taidi=Dog.class;
Method eat=taidi.getDeclaredMethod("eat");//拿无参的eat方法
7.3.2 有参的
Class jing=Dog.class;
Method eat1=jing.getDeclaredMethod("eat", String.class);//拿有参的eat方法
8 执行方法
8.1 public Object invoke(Object obj, Object… args)
触发某个对象的该方法执行
8.1.1无参方法
Class taidi=Dog.class;
Method eat=taidi.getDeclaredMethod("eat");//拿无参的eat方法
System.out.println(eat.getName()+"-->"+eat.getParameterCount()+"-->"+eat.getReturnType());
//触发该无参方法
Dog dog1=new Dog();
eat.setAccessible(true);//因为无参的eat方法是private的因此设置暴力发射
Object rs=eat.invoke(dog1);//调用无参的eat方法,用dog1对象触发调用
System.out.println(rs);//返回null,因为eat无参方法的返回类型是void的
8.1.2 有参方法
//获取某个方法(有参的)
Class jing=Dog.class;
Method eat1=jing.getDeclaredMethod("eat", String.class);
System.out.println(eat1.getName()+"-->"+eat1.getParameterCount()+"-->"+eat1.getReturnType());
//调用有参的eat方法
Dog dog2=new Dog();
eat1.setAccessible(true);
String rs1=(String) eat1.invoke(dog1,"狗粮");//调用有参的eat方法,用dog2对象触发调用
System.out.println(rs1);
System.out.println("===========");
9 反射的作用,应用场景
基本作用:
- 得到一个类的全部成分然后进行操作
- 破坏封装性
- 最重要的用途:适合做java框架,基本上,主流的框架都会基于反射设计出一些通用的功能
9.1 使用反射做一个简易框架
public class ObjectFrame {//目标:保存任意对象的字段和其数据到文件中去public static void saveObject(Object object) throws IllegalAccessException, FileNotFoundException {PrintStream ps = new PrintStream(new FileOutputStream("src\\data.txt", true));//obj是任意对象,到底有多少个字段可以保存Class c=object.getClass();String className=c.getSimpleName();ps.println("-----"+className+"-----");//从这个类中提取他的全部成员变量Field[] fields=c.getDeclaredFields();//遍历每个成员变量for(Field f:fields){//拿到成员变量的名字String name = f.getName();//拿到成员变量在对象中的数据f.setAccessible(true);String value= f.get(object) +"" ;ps.println(name+"="+value);}ps.close();}
}
public class TestFrame {public static void save() throws FileNotFoundException, IllegalAccessException {Student s1=new Student("张三",18,'男',178.9,"打篮球");Teacher t1=new Teacher("黎明",8000.1);ObjectFrame.saveObject(s1);ObjectFrame.saveObject(t1);}public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {save();}
}
xception {Student s1=new Student("张三",18,'男',178.9,"打篮球");Teacher t1=new Teacher("黎明",8000.1);ObjectFrame.saveObject(s1);ObjectFrame.saveObject(t1);}public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {save();}
}