您的位置:首页 > 编程语言 > Java开发

java反射机制

2016-05-26 09:42 716 查看
这是以前看了毕向东老师的视频所做的笔记,刚开始还是有点不理解,不过一两年再回头看看,其实自己做的笔记好像自己看的很有意思。(废话)

先看下面这幅图吧,看到什么



---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



一个类有多个组成部分,例如:成年变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。
反射技术一般用于框架中的获取,比如某个程序已经做好运行了,不可能再进行源代码的更改,此时想添加功能或修改,则我们自己写的代码怎么能放进去呢,这时就用到反射技术进行解剖类和方法,把我们的代码放进去。

编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?
比如:我们已经弄好了一个项目,那么项目里面的接口都是已经封装好的了 ,我们不可以直接调用里面的属性或方法,那么这时就用到反射了

java中有一个Class类用于代表某一个类的字节码。
Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:
forName();forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。
另外两种得到class对象的方式
类名.class
对象.getClass()

//反射,加载类 获得类的字节码
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException{
//1
Class clazz=Class.forName("cn.itcast.demo.Demo4");
//2
Class clazz1=new Demo4().getClass();
//3
Class clazz2=Demo4.class;
}

}


package cn.itcast.bean;
/*java反射机制是在运行状态中,对于任意一个类(class文件),都能够
* 知道这个类的所有属性和方法。
* 这种动态获取的信息,就是java反射。
* 可以理解为对类的解剖。
*
* 要想要对字节码文件进行解剖,必须要有字节码文件对象。
* 如何让获取字节码文件对象呢?
*
*
* */

public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
getClassObject_3();

}
/*方式3:
* 只要通过给定类的字符串名称就可以获取该类,更为扩展。
* 可以用Class类中的方法完成。
* 该方法就是forName
* 这种方式只要有名称即可,更为方便,扩展性更强。
* */
public  static void getClassObject_3() throws ClassNotFoundException {
String className="cn.itcast.been.Person";
Class clazz=Class.forName(className);
System.out.println(clazz);
}
/*方式2:
* 2.任何数据类型都具备一个静态的属性.class来获取其对应的class对象。
*相对简单,但是还是需要明确用到类中的静态成员。
*还是不够扩展。
*/
private static void getClassObject_2() {
Class clazz=Person.class;
Class clazz1=Person.class;
System.out.println(clazz==clazz1);
}
/*获取字节码对象的方式:
*1.Object类中的getClass()方法的。
*想要用这种方式必须要明确具体的类,并创建对象。
*
* */
public static void getClassObject_1(){
Person p=new Person();
Class clazz=p.getClass();

Person p1=new Person();
Class clazz1=p1.getClass();

System.out.println(clazz==clazz1);
}

}


package cn.itcast.bean;

public class Person {
private int age;
private String name;
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
System.out.println("Person param run..."+this.name+":"+this.age);
}
public Person(){
super();
System.out.println("person run");
}
public void show(){
System.out.println(name+"...show run..."+age);
}
private void method(){
System.out.println("method run");
}
public void paramMethod(String str,int num){
System.out.println("paramMethod run..."+str+":"+num);
}
public static void staticMethod(){
System.out.println("static method run...");
}
}


Class对象提供如下常用方法:

public Constructor getConstructor(Class<?>...parameterTypes):获取字节码
public Method getMethod (Stringname.Class<?>...parameterTypes):获取方法
public Field getField (String name):获取字段)
Declared(可以拿类中的所有内容包括私有的)
public Constructor getDeclaredConstructor(Class...parameterTypes)
public Method getDeclaredMethod (Stringname.Class...parameterTypes)
public Field getDeclaredField (String name)
这些方法分别用于从类中解剖出构造函数、方法、成员变量(属性)。
解剖出的成员分别使用Constructor、Method、Field对象表示。
思考:假设你是一个框架的设计者,解剖出这些成员你会干什么?
反射类的构造函数


利用Constructor创建对象
Constructor类提供了如下方法,用于创建类的对象:
public Object newInstance(Object...initargs)
initargs用于指定构造函数接收的参数
练习:反射类无参、有参、私有的构造函数,创建类的对象。
多学一招:sun公司为简化开发人员创建对象,它在class对象中也提供了一个newInstance方法,用于创建类的对象。这样开发人员可以避免每次都需要去反射Constructor类创建对象。
不过需要注意的是:class.newInstance方法内部是反射类无参的构造函数创建对象,所以利用此种方式创建类对象时,类必须有一个无参的构造函数。
反射类的方法

利用Method执行方法
Method对象提供 了如下方法,用于执行它所代表的方法。
public Object invoke(Objectobj,Object...args)
练习:使用Method分别执行无参、有参、多个参(带数组和基本数据类型)、静态、私有的方法。
jdk1.4和jdk1.5的invoke方法的区别:
jdk1.5:public Object invoke(Object obj,Object...args)
jdk1.4:public Object invoke(Object obj,Object[]...args)
反射机制(获取Class中的构造函数)
package cn.itcast.bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
createNewObject_2();

}
public static void createNewObject_2() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
//		cn.itcast.bean.Person p=new cn.itcast.bean.Person(39,"小强");
/*
* 当获取指定名称对应类中的所体现的对象时,
* 而该对象初始化不使用空参数构造该怎么办呢?
* 既然是通过指定的构造函数 进行对象的初始化,
* 所以应该先获取到该构造函数。了、通过字节码文件对象即可完成。
* 该方法是:getConstructor(paramterTypes)
* */
String name="cn.itcast.bean.Person";
Class clazz=Class.forName(name);
Constructor constructor=clazz.getConstructor(String.class,int.class);
//通过该构造器对象的newInstance方法进行对象的初始化。
Object obj=constructor.newInstance("小明",38);
}
public static void createNewObject()throws ClassNotFoundException, InstantiationException, IllegalAccessException{
//早期:new 的时候,先根据new的类的名称寻找该类的字节码文件,并加载进内存,
//并创建该字节码文件对象,并接着创建该字节码文件的对应的Person对象。
//cn.itcast.bean.Person p=new cn.itcast.bean.Person();

//现在
String name="cn.itcast.bean.Person";
//寻找该名称类文件,并加载进内存,并产生Class对象。
Class clazz=Class.forName(name);
//如何产生该类的对象呢?
Object obj=clazz.newInstance();
}

}
反射机制(获取Class中的字段)

package cn.itcast.bean;

import java.lang.reflect.Field;

public class ReflectDemo3 {
public static void main(String[] args) throws SecurityException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IllegalAccessException {
getFiledDemo();
}
public static void getFiledDemo() throws SecurityException, NoSuchFieldException, ClassNotFoundException, InstantiationException, IllegalAccessException {
Class clazz=Class.forName("cn.itcast.bean.Person");
//Field field=clazz.getField("age");//只能获取公共的
Field field=clazz.getDeclaredField("age");//只获取本类,但包含私有。
//对私有字段的访问取消权限检查。
field.setAccessible(true);
Object obj=clazz.newInstance();
Object o=field.get(obj);
System.out.println(o);
}
}


反射机制(获取Class中的方法)
package cn.itcast.bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo4 {
public static void main(String[] args) throws Exception {
getMethodDemo_3();

}

public static void getMethodDemo_3() throws Exception {
Class clazz=Class.forName("cn.itcast.bean.Person");
Method method=clazz.getMethod("paramMethod",String.class,int.class);
Object obj=clazz.newInstance();
method.invoke(obj, "小强",89);

}

public static void getMethodDemo_2() throws Exception {
Class clazz=Class.forName("cn.itcast.bean.Person");
Method method=clazz.getMethod("show",null);//获取show空参数方法
//		Object obj=clazz.newInstance();
Constructor constructor=clazz.getConstructor(String.class,int.class);
Object obj=constructor.newInstance("小明",37);
method.invoke(obj, null);
}

public static void getMethodDemo() throws Exception {
Class clazz=Class.forName("cn.itcase.bean.Person");
Method[]methods=clazz.getMethods();//获取的都是公有的方法
methods=clazz.getDeclaredMethods();//指获取本类中所有方法,包含私有的。
for(Method method:methods){
System.out.println(method);
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: