反射就是在程序运行中,动态的创建对象,只要知道该类的名称,就能用它的字节码对象创建该类的对象(实例) 从而访问该类的任何方法和属性(暴力访问)
- 什么是字节码对象?
javac 编译java文件后得到的class文件就是该类的字节码文件
javac Person.java//得到---------Person.class文件
- 获得字节码的几种方法:
1.Object类的getclass方法------构造函数私有时无法new
2.类.class
3.class类的静态方法forname("类全路径")方法
》》》字节码对象.newinstance得到对象实例
- 类和class对象关系
成员变量……fields
成员方法……methods
构造函数……constructor
- 具体事例:
事例说明:
单独一个Person类 其中属性,方法,以及构造方法都是公有,私有共存
public class Person { private String name; public String password; String description; public void add(String na) { System.out.println("公有" + na); } private void find(String pass) { System.out.println("私有" + pass); } public Person() { super(); // TODO Auto-generated constructor stub } private Person(String name, String password, String description) { super(); this.name = name; this.password = password; this.description = description; System.out.println("私有的构造函数:"+name+password+description); } }
1.通过反射得到fields(成员属性),就是通过反射得到Person的私有属性-------一般方法没法获得
Class class1 = Class.forName("cn.itcast.reflect.Person");//获得字节码对象 //访问私有属性-------------fields Field[] fields=class1.getDeclaredFields();//获得多个属性 返回数组 for (Field field : fields) { System.out.println(field); }
结果:
private java.lang.String cn.itcast.reflect.Person.name public java.lang.String cn.itcast.reflect.Person.password java.lang.String cn.itcast.reflect.Person.description
2.通过反射访问methods(成员方法),通过反射得到Person的私有方法:
注意Person类中的find(){}方法-----私有的
private void find(String pass) { System.out.println("私有" + pass); }
暴力访问:
public static void main(String[] args) throws Exception {
Class class1 = Class.forName("cn.itcast.reflect.Person");//获得字节码对象
Person person=(Person) class1.newInstance();//创建对象实例 Method[] methods=class1.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } Method method=class1.getDeclaredMethod("find",String.class); method.setAccessible(true);//没有这个结果将报错 method.invoke(person, "12333"); }
结果:
public void cn.itcast.reflect.Person.add(java.lang.String) private void cn.itcast.reflect.Person.find(java.lang.String) 私有12333
3.通过反射访问constructor(构造函数)
public static void main(String[] args) throws Exception { Class class1 = Class.forName("cn.itcast.reflect.Person");//获得字节码对象 Constructor[] con=class1.getDeclaredConstructors(); for (Constructor constructor : con) { System.out.println(constructor); } Constructor co=class1.getDeclaredConstructor(String.class,String.class,String.class); co.setAccessible(true); Person p=(Person) co.newInstance("da","xiao","da"); System.out.println(p); }
结果:
private cn.itcast.reflect.Person(java.lang.String,java.lang.String,java.lang.String) public cn.itcast.reflect.Person() 私有的构造函数:daxiaoda cn.itcast.reflect.Person@139a55
- 与单例设计模式
单例设计模式核心就是构造函数私有化,但是通过java反射机制可以破坏这种模式,通过反射还是可以访问私有构造函数
》》》》》装逼小福利:静态代码块中的语句没有main方法也可以编译,但是代码块末尾加system.exit(0)
Public Person{ static { System.out.println("hello!!!"); System.exit(0); //这句是为了防止编译报错 } }