反射是被视为动态语言的关键,反射机制允许程序在执行期间借助Reflection API来获取类的内部信息(如类的属性和方法),并能够直接操作对象的内部属性和方法。
加载完类之后,在堆内存会产生一个Class类型的对象(一个类在堆中会有多个对象,但是只有一个Class对象)这个Class对象包含了完整的类的结构信息,我们可以通过这个Class对象来获取加载的这个类的结构和属性信息,这个过程称为反射
2.1,创建Person类
public class Person {private String name;public int age;private String nation;public Person() {}public String getName() {return name;}public String getNation() {return nation;}public void setNation(String nation) {this.nation = nation;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public Person(String name, int age, String nation) {this.name = name;this.age = age;this.nation = nation;}public void setAge(int age) {this.age = age;}public Person(String name, int age) {this.name = name;this.age = age;}public void show(){System.out.println("你好,我是一个人");}public String shownation(){System.out.println("我的国籍是:"+nation);return this.nation;}
}
2.2,操作Person类中的属性
public static void main(String[] args) throws Exception{//获取Calss类对象Class claszz = Person.class; //通过反射创建类对象Person o = (Person)claszz.newInstance();//通过反射获取类的属性Field age1 = claszz.getField("age");age1.set(o,10);System.out.println(o.getAge());}
public static void main(String[] args) throws Exception{//获取Calss类对象Class claszz = Person.class;//通过反射创建类对象Person o = (Person)claszz.newInstance();//获取方法字段Method show = claszz.getDeclaredMethod("show");//执行方法,方法.invoke(对象)show.invoke(o);}
2.3,操作类中的私有属性
public static void main(String[] args) throws Exception{//获取Calss类对象Class clazz = Person.class;//通过反射创建类对象Person person = (Person)clazz.newInstance();Field name = clazz.getDeclaredField("name");name.setAccessible(true);name.set(person,"张三");System.out.println(person.getName());}
封装是防止外部调用内部私有属性或方法,而反射可以调用并操作内部的私有属性或方法,这是不是会有冲突呢
这是不矛盾的,封装解决的是建议我们怎么调的问题,反射解决的是我们怎么掉的问题。
我们知道Java是一个面向对象语言,一切都是对象,我们在声明一个类的时候如:Class User{}
其实User类就是一个Class的对象实例。Class User=new Class();其实User就是Class的对象。
获取类的一个对象
4,1,创建Class的实例的方式
Class的一个实例就对应一个运行时类(这里就是Person类),加载到内存中的运行时类会缓存一段时间,在这个时间内,我们可以通过不同的方式来获取此运行时类(Person类)。
public static void main(String[] args) throws Exception{Properties pro=new Properties();FileInputStream fileInputStream=new FileInputStream("application.properties");pro.load(fileInputStream);String user=pro.getProperty("name");System.out.println(user);}
public static void main(String[] args) throws Exception{Class clazz = Person.class;Object o = clazz.newInstance();System.out.println(o.getClass().getName());}
其实这里面newinstance()是通过调用无参构造函数来创建对象实例。
6.1,反射的动态性
我们知道反射最大的特性就是动态性,就是在编译时是无法确定结果的,只有在运行是才会确定结果。
public static Object getInstane(String classPath) throws Exception {Class aClass = Class.forName(classPath);Object o = aClass.newInstance();return o;}
我们利用发射动态性来动态的创建对象。
public static void main(String[] args) throws Exception {int num=new Random().nextInt(3);String classPath="";switch (num){case 1:classPath="reflection.User";break;case 2:classPath="java.sql.Date";break;case 3:classPath="reflection.Person";break;}System.out.println(getInstane(classPath).getClass().getName());}
我们只有在运行时才能确定对象类型,这就是发射的动态性。