java之反射

来源:互联网 发布:男人射精前的样子知乎 编辑:程序博客网 时间:2024/05/23 01:12

反射

1:反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;

 对于任意一个对象,都能调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制

 

2:学习反射需要有以下步骤

A:首先学习字节码文件

B:第二学习获取字节码文件的构造方法 并创建对象

C:有了对象了,就要学会获取对象中的成员变量

D:能获取对象中的成员变量了,那么还要学习成员方法

 

 

1)字节码文件的三种获取方式

 

Object类的getClass()方法:对象.getClass()

Personp = new Person();

Classc = p.getClass();

注意所有同一个类的字节码文件对象(实例)都是同一个(因为一个类就有唯一的字节码文件)

比如:  Person p = new Person();

Classc = p.getClass();

 

Personp2 = new Person();

Classc2 = p2.getClass();

 

System.out.println(p== p2);// false

System.out.println(c== c2);// true

 

:数据类型的静态的class属性:类名.class

Classc3 = Person.class;

 

:通过Class类的静态方法forName(String className)(一般只用最后一种,前面两种了解即可)

Classc4 = Class.forName("cn.itcast_01.Person");

 

2)反射获取类的构造方法

public Constructor<?>[] getConstructors():所有公共构造方法

public Constructor<?>[]getDeclaredConstructors():所有构造方法包括私有

public Constructor<T>getConstructor(Class<?>... parameterTypes):获取单个构造方法

比如:

Classclazz = Class.forName("com.heima.bean.Person");

Constructor c =clazz.getConstructor(String.class,int.class);        //获取有参构造

Person p = (Person) c.newInstance("张三",23);                                                //通过有参构造创建对象

System.out.println(p);

 

 

3)反射获取类的成员变量

Field[] fields = c.getFields();//获取所有公共的成员变量

Field[] fields = c.getDeclaredFields();//获取所有的成员变量

Field field = c.getField("age");//获取单个的成员变量

 

比如:

Classclazz = Class.forName("com.heima.bean.Person");

Constructor c =clazz.getConstructor(String.class,int.class);        //获取有参构造

Person p = (Person) c.newInstance("张三",23);                                                //通过有参构造创建对象                                                                                                //修改姓名的值

Field f =clazz.getDeclaredField("name");                                                //暴力反射获取字段

f.setAccessible(true);                                                                                        //去除私有权限

f.set(p, "李四");        

System.out.println(p);

 

 

4)反射获取类的成员方法

Method[] methods = c.getMethods();//所有公共方法,包括父类的

Method[] methods = c.getDeclaredMethods();//本类的所有方法

 

Classclazz = Class.forName("com.heima.bean.Person");

Constructor c =clazz.getConstructor(String.class,int.class);        //获取有参构造

Person p = (Person) c.newInstance("张三",23);                                                //通过有参构造创建对象

 

Method m =clazz.getMethod("eat");                                                                //获取eat方法

m.invoke(p);

 

Method m2 =clazz.getMethod("eat",int.class);                                        //获取有参的eat方法

m2.invoke(p,10);

 

 

3:案例:动态创建某个配置文件中提供的一个类的名字的这个类的对象,并执行其方法        

 

publicclass DemoClass {

publicvoid run() {

System.out.println("welcometo heima!");

}

}

 

 

BufferedReader br = newBufferedReader(newFileReader("xxx.properties"));        //创建输入流关联xxx.properties

Class clazz =Class.forName(br.readLine());                                                                        //读取配置文件中类名,获取字节码对象

 

DemoClass dc = (DemoClass)clazz.newInstance();                                                                //通过字节码对象创建对象

dc.run();

 

 

4:泛型只是在编译期间

等编译通过生成了字节码文件后,泛型就会被擦除,运行期间就没有泛型了

ArrayList<Integer>list = new ArrayList<>();

list.add(111);

list.add(222);

 

Class clazz =Class.forName("java.util.ArrayList");                                //获取字节码对象

Method m =clazz.getMethod("add",Object.class);                                //获取add方法

m.invoke(list,"abc");

 

System.out.println(list);

5: public void setProperty(Object obj, StringpropertyName, Object value){}

此方法可将obj对象中名为propertyName的属性的值设置为value

 

publicclass Tool {

//此方法可将obj对象中名为propertyName的属性的值设置为value

publicvoid setProperty(Object obj, String propertyName, Object value) throwsException {

Class clazz =obj.getClass();                                        //获取字节码对象

Field f =clazz.getDeclaredField(propertyName);        //暴力反射获取字段

f.setAccessible(true);                                                        //去除权限

f.set(obj,value);

}

}

 

publicstatic void main(String[] args) throws Exception {

Student s = new Student("张三", 23);

System.out.println(s);

 

Toolt = new Tool();

t.setProperty(s, "name","李四");

System.out.println(s);

}

 

动态代理

 

publicinterface Student {

publicvoid login();

 

publicvoid submit();

}

 

publicclass StudentImp implements Student {

 

@Override

publicvoid login() {

System.out.println("登录");

}

 

@Override

publicvoid submit() {

System.out.println("提交");

}

 

}

publicclass MyInvocationHandler implements InvocationHandler {

privateObject target;

 

publicMyInvocationHandler(Object target) {

this.target= target;

}

@Override

publicObject invoke(Object proxy, Method method, Object[] args)

throwsThrowable {

System.out.println("权限校验");

method.invoke(target,args);                                        //执行被代理target对象的方法

System.out.println("日志记录");

returnnull;

}

 

}

 

 

StudentImpsi = new StudentImp();

si.login();

si.submit();

 

System.out.println("-------------------------------");

MyInvocationHandlerm = new MyInvocationHandler(si);

Students = (Student)Proxy.newProxyInstance(si.getClass().getClassLoader(),si.getClass().getInterfaces(), m);

 

s.login();

s.submit();


1 0
原创粉丝点击