反射
认识反射,获取类
获取类中的成分,并对其进行操作
作用、应用场景。
认识反射,获取类
反射:加载类,并允许以编程的方式解剖类中的各种成分(成员变量,方法,构造器等)。
反射学什么?
学习获取类的信息,操作它们
1、反射第一步:加载类,获取类的字节码:Class对象。
2、获取类中的构造器:Constructor
3、获取类的成员变量:Field对象
4、获取类的成员方法:Method对象
获取Class对象的三种方式
Class c1=类名.class
调用Class提供方法:public static Class forName(String package)
Object提供的方法:public Class getClass(); Class c3=对象.getClass();
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
//1获得类本身 类.class
Class c1=Student.class;
System.out.println(c1);
//2获得类本身 Class.forName("全类名")
Class c2=Class.forName("Student");
System.out.println(c2);
//3获得类本身 对象.getClass()
Student s=new Student();
Class c3=s.getClass();
System.out.println(c3);
}
}
Class提供了从类中获取构造器的方法。
方法 | 说明 |
Constructor<?>[ ] getConstructors() | 获取全部构造器(只能获取public修饰的) |
Constructor<?>[] getDeclaredConstructors() | 获取全部构造器(只要存在就能拿到) |
Constructor<T>getConstructor (Class<?...parameterTypes>) | 获取某个构造器(只能获得public修饰的) |
Constructor<T>getDeclaredConstructor (Class<?...parameterTypes>) | 获取某个构造器(只要存在就能拿到) |
Class提供了从类中获取成员方法的api
方法 | 说明 |
Method[ ]getMethods() | 获取类的全部成员方法(只能获得public修饰的) |
Method[ ]getDeclareMethods() | 获取类的全部成员方法(只要存在就能拿到) |
Method getMethod(String name,Class<?...parameterTypes>) | 触发某个对象的该方法执行。 |
Method getDeclareMethod(String name,Class<?...parameterTypes>) | 获取类的某个成员方法(只要存在就能拿到) |
以上面两个为例获取所有类中的成分
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Class c1=Student.class;
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
}
@Test
//2获取类的构造器对象
public void getConstructor() throws Exception{
Class c1=Dog.class;
Constructor[] cs=c1.getDeclaredConstructors();
for(Constructor c:cs){
System.out.println(c.getName()+" ");
}
//获取单个构造器
Constructor c2=c1.getDeclaredConstructor(String.class,int.class);
System.out.println(c2);
//获取构造器的作用依然是创建对象:创建对象,
//暴力反射
c2.setAccessible(true);
Dog o=(Dog)c2.newInstance("小花",12);
System.out.println(o);
}
@Test
//获取类的成员变量对象并对其进行操作
public void getField() throws Exception{
Class c1=Student.class;
//获取所有成员变量对象
Field[] fields=c1.getDeclaredFields();
for(Field f:fields){
System.out.println(f.getName());
}
//获取单个成员变量对象
Field f1=c1.getDeclaredField("name");
System.out.println(f1);
Dog d=new Dog("小花",13);
f1.setAccessible(true);
f1.set(d,"小花花");
String name= (String) f1.get(d);
}
@Test
public void getMethod() throws Exception{
//获取类的成员方法对象并对其进行操作
Class c1=Student.class;
Method[] methods=c1.getDeclaredMethods();
for(Method m:methods){
System.out.println(m.getName());
}
Method m1=c1.getDeclaredMethod("study",String.class);
调用成员方法对象
Student s=new Student("小明",12);
m1.invoke(s,"java");
}
}
反射的基本作用有哪些?
反射的作用?
基本作用:可以得到一个类的全部成分然后操作。
可以破坏封装性。
可以绕过泛型的约束。
最重要的用途是:适合做java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ReflectDemo4 {
public static void main(String[] args) throws Exception{
ArrayList<String> list=new ArrayList<>();
list.add("hello");
list.add("world");
list.add("java");
Class c1=list.getClass();
Method m1=c1.getDeclaredMethod("add",Object.class);
m1.invoke(list,5);
}
}
写一个反射框架
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class SaveObjectFrameWork {
public static void saveObject(Object obj)throws Exception
{
PrintStream ps=new PrintStream(new FileOutputStream("ReflectDemo1/src/obj.txt",true));
Class c=obj.getClass();
ps.println("--------------"+c.getSimpleName()+"-----------------");
Field[] fields=c.getDeclaredFields();
for(Field f:fields)
{
f.setAccessible(true);
String name=f.getName();
String value=f.get(obj)+" ";
ps.println(name+":"+value);
}
ps.close();
}
}
public class ReflectDemo6 {
public static void main(String[] args) throws Exception{
Student s=new Student("小马",18,"爱问问题");
SaveObjectFrameWork.saveObject(s);
Dog d=new Dog("小花",3);
SaveObjectFrameWork.saveObject(d);
Teacher t=new Teacher("小明",20,"java",5000,"211","女生","123213213123");
SaveObjectFrameWork.saveObject(t);
}
}