反射
框架的灵魂
反射:将类的各个组成部分分装为其他对象,这事就是反射机制
Java反射机制是在运行状态中,对于任意一个类们都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它任意一个方法和属性,这种动态获取信息以及动态调用对象的方法的功能称为反射
好处:
- 可以在程序运行过程中,操作这些对象
- 可以解耦,提高程序的可扩展性
Person类
package com.company;
public class Person {
String name;
Integer age;
private String gender;
public Person(){
super();
}
public Person(String name,Integer age){
super();
this.name=name;
this.age=age;
}
public void show(){
System.out.println("我是"+this.name+"年龄"+this.age+"gender");
}
}
Main类
package com.company;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
//获取字节码
Class clazz=Class.forName("com.company.Person");
Class clazz2=Person.class;
Person p=new Person();
Class clazz3=p.getClass();
//以上三种方式获取的字节码相等
}
}
getClass和.Class区别?
我们一般所使用的对象都直接或间接继承自Object类,getClass()是Object类的方法,它可以获得一个实例的类型类。
类型类指的是代表一个类型的类,因为一切皆是对象,类型也不例外,在Java使用类型类来表示一个类型。所有的类型类都是Class类的实例。
public static void main(String[] args) {
ClassA a=new ClassA();
System.out.println(a.getClass());
System.out.println(ClassA.class);
}对象a是A的一个实例,ClassA是某一个类,在Java中表示一个特定类型的类型类可以用“类型.class”的方式获得,因为a.getClass()获得是ClassA的类型类,也就是ClassA.class。所以ClassA.class和a.getClass()是一样的。
类型类是一一对应的,父类的类型类和子类的类型类是不同的,因此,假设ClassA是ClassB的子类,那么ClassB.class和a.getClass是不一样的。getClass方法,有多态能力,运行时可以返回子类的类型信息,
.class是没有多态的,是静态解析的,编译时可以确定类型信息
构造器使用
package com.company;
import java.lang.reflect.Constructor;
public class Main {
public static void main(String[] args) throws Exception {
//获取字节码
Class<Person> clazz2=Person.class;
//以上三种方式获取的字节码相等
Person p = clazz2.newInstance();
p.name="zs";
p.age=10;
p.show();
//通过参数的构造器来创建对象
//先去获取构造器
Constructor c = clazz2.getConstructor(String.class, Integer.class);
//通过构造器来创建对象
Person p2=(Person)c.newInstance("鲁班",7);
p2.show();
}
}
通过反射获取字段与方法
package com.company;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
//获取字节码
Class<Person> clazz2=Person.class;
Person p = clazz2.newInstance();
p.name="zs";
p.age=10;
p.show();
//通过参数的构造器来创建对象
//先去获取构造器
Constructor c = clazz2.getConstructor(String.class, Integer.class);
//通过构造器来创建对象
Person p2=(Person)c.newInstance("鲁班",7);
p2.show();
//获取字段
Field f= clazz2.getField("name");
f.set(p2,"李白");
p2.show();
//获取私有的字段
Field f2=clazz2.getDeclaredField("gender");
//去除私有权限
f2.setAccessible(true);
f2.set(p2,"男");
p2.show();
//获取公共方法
Method m1=clazz2.getMethod("show");
System.out.println(m1.getName());
m1.invoke(p2);
//获取私有方法 方法名称 方法参数
Method m2=clazz2.getDeclaredMethod("eat",String.class);
//去除私有的权限
m2.setAccessible(true);
m2.invoke(p2,"米饭");
}
}
通过反射越过arraylist的类型检测
泛型在编译成字节码的时候会把泛型擦除
package com.company;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws Exception {
ArrayList<Integer>list=new ArrayList<>();
list.add(1);
Class<?>clazz= Class.forName("java.util.ArrayList");
clazz.getMethod("add",Object.class);
Method m =clazz.getMethod("add",Object.class);
m.invoke(list,"myxq");
System.out.println(list);
}
}