什么是反射?
通过字节码对象创建对象,获取构造器,方法,字段
什么是字节码对象?
JVM将java类编译成一份份字节码文件(.class),因此从众多的字节码文件中抽取出他们的共性形成一个Class类,该类具有所有字节码文件的特点(字段,方法,构造器),因此该类的对象被称为字节码对象
可以通过字节码对象去创建对象,操作该类中的方法/字段/构造器/这种过程成为反射
反射主要掌握字节码的获取,一般使用forName(“全限定名”)的方式
其余所有的操作都是根据字节码对象来操作的
获取构造器/方法/字段/创建对象
1.反射的使用场景
有些时候我们无法看到源码,不知道一个对象的具体类型,此时无法强转
这个时候就需要用到反射,去获取该对象的信息
2.反射的基本使用
(1).获取字节码对象
三种方式:
类名.class
对象名.getClass()
forName(“全限定名”)
(2).获取构造器
通过字节码对象获取/所有构造器/指定构造器/公共的/全部包括私有(getDeclared…)
(3).获取方法
通过字节码对象获取/所有方法/指定方法/公共的/全部包括私有(getDeclared…)
(4).获取字段
通过字节码对象获取/所有字段/指定字段/公共的/全部包括私有(getDeclared…)
注意:
在使用反射时注意参数的传递,比如形参传递的是类型(如:String.class,因为是通过字节码对象获取的构造器/方法,所以这里也需使用字节码对象的类型);
在使用Declared的构造器/方法/字段时,要设置访问权限Accessible;
因为创建对象的时候使用公共无参构造器的频率比较高,所以使用 字节码对象.newInstance可以直接创建对象;
代码片
public void testInstance1() throws Exception {
//获取字节码对象的三种方式
//方式一
Class clz1 = Class.forName("com.reflect.User");
//方式二
//User u=new User();
//Class clz2= u.getClass();
//方式三
Class clz3=User.class;
//通常使用forName();
//获取所有公共的构造器
Constructor[] constructors = clz1.getConstructors();
for (Constructor con : constructors) {
System.out.println(con);
}
System.out.println("--------------------------------------");
//获取所有的构造方法包括私有的
Constructor[] con2 = clz1.getDeclaredConstructors();
for (Constructor cons : con2) {
System.out.println(cons);
}
// 获取公共无参构造器
Constructor constructor = clz1.getConstructor();
// 使用无参构造器创建对象
Object obj = constructor.newInstance();
// 获取方法一
Method m = clz1.getMethod("method1");
m.invoke(obj, null);
}
@Test
public void testinstance2() throws Exception {
Class clz1 = Class.forName("com.reflect.User");
//获取三个参数的构造器
Constructor con=clz1.getConstructor(String.class,int.class,String.class);
//使用三参数的构造器创建对象
Object obj = con.newInstance("王昭君",24,"女");
System.out.println(obj);
System.out.println("------------------------------------");
//获取所有的公共的方法
Method[] methods = clz1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("------------------------------------");
//获取所有的方法包括私有的
Method[] declar = clz1.getDeclaredMethods();
for (Method method : declar) {
System.out.println(method);
}
System.out.println("------------------------------------");
//获取含参数的方法,形参为参数类型
Method method = clz1.getMethod("method2", String.class);
//调用方法 传入实参
method.invoke(obj, "貂蝉");
}
@Test
public void testinstance3() throws Exception {
Class clz1 = Class.forName("com.reflect.User");
//获取私有的构造器
Constructor con=clz1.getDeclaredConstructor(String.class,int.class);
//设置访问权限为true
con.setAccessible(true);
Object obj=con.newInstance("吕布",2);
System.out.println(obj);
//获取私有的方法
Method m=clz1.getDeclaredMethod("method4", String.class);
//设置访问权限
m.setAccessible(true);
//调用
m.invoke(obj, "张飞");
}
@Test
public void testinstance4() throws Exception {
Class clz1 = Class.forName("com.reflect.User");
//使用公共无参构造器创建对象,使用太频繁,精简操作
Object instance = clz1.newInstance();
System.out.println(instance);
}
@Test
public void testFileds() throws Exception {
Class clz1 = Class.forName("com.reflect.User");
//获取所有字段
Field[] fields = clz1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
Object obj = clz1.newInstance();
//获取指定字段
Field fName = clz1.getDeclaredField("name");
fName.setAccessible(true);
//给指定字段赋值
fName.set(obj, "鲁班");
Field fAge = clz1.getDeclaredField("age");
fAge.setAccessible(true);
fAge.set(obj, 2);
Field fGender = clz1.getField("gender");
fGender.set(obj, "女");
System.out.println(obj);
}
学习阶段,如有问题,欢迎指正