您的位置:首页 > 其它

反射机制复习总结

2016-01-04 22:04 183 查看

JAVA反射机制

是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

ava的反射是大多数框架的基础,如struts,Hibernate和Spring等。

通过反射机制可以获得一个陌生的java类的所有信息。如属性,方法,构造器,修饰符等。

也就是说反射是为了能够动态地加载一个类,动态地调用一个方法,动态地访问一个属性等动态的要求而设计的。它的出发点在于JVM会为每个 类创建一个java.lang.Class类的实例,通过这个对象可以获得这个类的信息。

反射机制的API主要集中在java.lang.reflect包下面。

获得对象运行时的类,可以实现动态创建对象和编译,体现出很大的灵活性

Class.class是对所有类抽象出来的类

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

Java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法;

生成动态代理。

Class类:

众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。

Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。

当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。

Class对象

Class并没有public constructor。它的private Class() {},意指不允许任何人经由编程方式产生Class object。其object 只能由JVM 产生。

获取方法

1)运用getClass()

注:每个class 都有此函数

String str = “abc”;

Class c1 = str.getClass();

2)运用Class.getSuperclass()

Button b = new Button();

Class c1 = b.getClass();

Class c2 = c1.getSuperclass();

3)运用static method——Class.forName()(最常被使用)

Class c1 = Class.forName (“java.lang.String”);

4)运用primitive wrapper classes的TYPE 语法

Class c1 = Boolean.TYPE;

Class c2 = Byte.TYPE;

5)访问所有类都会有的静态的class属性。

Class clazz3 = Person.class;

Class intClazz = int.class;

Class voidClazz = void.class;

Field类

Field类,代表的是类的属性(字段)

Field对象通过Class类的getDeclaredFields()或getDeclaredField()方法获得。

获得类中定义的所有属性

1.获得所有属性对象组成的数组,包括私有,非继承的,
Field[] fields = clazz.getDeclaredFields();
2.遍历该数组,获得每个元素分别表示每个属性
for(Field f : fields) {
3.打印属性的类型和名字
String name = f.getName();
String type = f.getType().getName();
//Object value = f.get(obj); obj为要访问的属性所在的对象名,访问类private的成员,会抛非法访问异常
System.out.println("类型:" + type + "属性名:" + name);
}


访问以下obj对象私有name属性,并且改变name属性

Field nameField = clazz.getDeclaredField(“name”);//此处为私有属性

nameField.setAccessible(true); //取消Java编译器对该属性的访问权限语法检查用反射机制可以打破封装性,导致了java对象的属性不安全。

Object value = nameField.get(obj);//用get方法指定是哪个对象的属性

System.out.println(value);

nameField.set(obj, “wangwu”);

Method setNameMethod = clazz.getDeclaredMethod(“setName”, String.class);//第二个为可变形参类型

//Method setNameMethod = clazz.getDeclaredMethod(“setName”, new Class[]{String.class});

setNameMethod.invoke(obj, “lisi”);//第二个为可变实参数

获得类中定义的构造方法

Constructor[] constructors = clazz.getConstructors();

for(Constructor con : constructors) {

String name = con.getName();

System.out.print(“构造函数:” + name + “,参数类型依次为:”);

Class[] parameterTypes = con.getParameterTypes();

for(Class parameterType : parameterTypes)

System.out.print(parameterType.getName() + ” “);

System.out.println();

}

调用有参的构造函数,创建对象

Constructor constructor = clazz.getConstructor(new Class[]{String.class, int.class});

//GDK1.5之前都是用的数组,后来才用的可变参数,向前兼容所以数组也可以

或Constructor constructor = clazz.getConstructor(String.class, int.class);即参数是String与int类型的构造函数,

Person person = (Person) constructor.newInstance(“zhaoliu”, 33);

对数组参数

Constructor constructor=clazz.getConstructor(int[].class);

再(Person)constructor.newInstance(new Object[]{new int[]{参数,参数}})

System.out.println(person);

*/

用默认的构造函数创建对象

Class clazz= Person.class; Person you=(Person)clazz.newInstance();因为返回类型为object所以要强转

先获得构造方法再来实例化一个类是很麻烦的,会涉及到构造方法的查找和调用。所以要养成一个好习惯,没自定义一个类都提供一个无参的构造方法。这样就可以直接调用newInstance()方法来创建对象。

获得包名

Package pack = clazz.getPackage();

System.out.println(“包名为:” + pack.getName());

获得修饰符

/*int num = clazz.getModifiers();//当有多个修饰符时会相加

System.out.println(num);

if(num==Modifier.PUBLIC)

System.out.println(“这个类是public的”);

*/

if(Modifier.isPublic(num))

System.out.println(“这个类是public的”);

if(Modifier.isAbstract(num))

System.out.println(“这个类是Abstract的”);

if(Modifier.isInterface(num))

System.out.println(“这是一个接口”);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: