您的位置:首页 > 职场人生

黑马程序员——反射

2015-07-31 22:59 633 查看
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

反射

理解反射的概念

反射就是把Java类中的各种成分映射相成Java类。

例如:众多的人用一个Person类来表示,那么众多的Java类就用一个Class类来表示。


Class类

Class类用于表示.class文件,是所有加载进内存的字节码对象的父类。所以可以通过Class得到运行时的类。
同一个类实例化的不同对象得到的字节码是同一个


注意:

1、int.class == Integer.TYPE。

2、数组类型的Class实例对象Class.isArray()为true。

3、反射并不是Java 5.0的新特性。

常用方法

System.out.println("判断int基本数据类型和Integer的基本数据类型"

+ "是不是同一个Class对象 结果为:"+(int.class == Integer.TYPE));

System.out.println("判断int.class是不是基本数据类型 结果为:"+int.class.isPrimitive());

System.out.println("判断是不是数组类型 结果为:"+int[].class.isArray());


*构造方法的反射应用(Coustructor类)*

Constructor类的实例对象代表类的一个构造方法。

反射公共,私有和保护的构造方法:

反射公共的需要的方法是:getConstructor();

反射私有的需要的方法是:getDeclaredConstructor();


Constructor对象代表一个构造方法,Constructor对象有的方法:得到构造方法名字,得到所属于的类,产生实例对象。

得到某个类空参数构造方法,例:

Constructor constructor = Class.forName("java.lang.String").getConstructor();

得到某个类所有的构造方法,例:

Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一个带参数的构造方法,例:

Constructor constructor =Class.forName("java.lang.String").getConstructor(StringBuffer.class);


利用构造方法创建实例对象:

通常方式:String instance = new String(new StringBuffer("黑马程序员"));

反射方式:String instance = (String)constructor.newInstance("黑马程序员");


调用获得的方法时要用到上面相同类型的实例对象

通过Class类中的newInstance()方法也可创建类的实例,其内部工作原理是先得无参的构造方法,再用构造方法创建实例对象。

*成员变量的反射(Field类)*

Field类代表反射某个类中的一个成员变量。

注意访问权限的问题)也就是说,定义的是类对象,而非对象的对象。

代码示例

package com.itheima.study;
public class Person {
public int age;
private int height;
public Person(int age,int height){

this.age=age;
this.height=height;

}

}

package com.itheima.study;
import java.lang.reflect.Field;

public class ReflectTest{

public static void main(String...args) throws Exception{

Person p = new Person(20,30);

Field fieldAge = p.getClass().getField("age");

System.out.println(fieldAge.get(p));

}
}


注意:如果类的某个成员变量的修饰符是private,那么直接通过getField方法获取Field类型的对象就会出现错误。那么直接通过getDeclaredField方法获取Field。

通过称之为暴力反射的方式解决,也就是使用setAccessible(true)使private类型的成员变量也可以被获取值。


练习:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”CSDN社区”通过反射改成”黑马论坛”。

package 遍历E盘;

public class fanshe {
public String str1 = "CSDN社区";
public String str2 = "黑马程序员";
public String str3 = "啊苏打水";
@Override
public String toString() {
return str1 + "++" + str2 + "++" + str3;
}
}

package 遍历E盘;

import java.lang.reflect.Field;

public class fanshe1 {

public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
fanshe f = new fanshe();
changeStringValue(f);
System.out.println(f);
}
private static void changeStringValue(Object f) throws Exception, Exception {
// TODO Auto-generated method stub
Field[] ff= f.getClass().getFields();
for (Field i:ff) {
String s1=(String)i.get(f);//获取实例化对象所对应的字段值
String newValue = s1.replace("CSDN社区", "黑马论坛" );
i.set(f, newValue);//修改值
}
}

}


成员方法的反射(Method类)

Method类代表某个类中的一个成员方法

得到类中的某一个方法:

例子
Method charAt = Class.forName("java.lang.String").getMethod("charAt",
调用方法:

通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str, 1));


如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?

说明该Method对象对应的是一个静态方法!


JDK1.4和JDK1.5的invoke方法的区别:

JDK1.4:public Object invoke(Object obj,Object[] args)

JDK1.5:public Object invoke(Object obj,Object... args)


目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。

package com.itheima.day01;

import java.lang.reflect.Method;

public class ReflectTest {

public static void main(String[] args) throws Exception {
Class clszz = Class.forName(args[0]);
Method main = clszz.getMethod("main", String[].class);
main.invoke(null,"黑马程序员","黑马论坛","CSDN社区");
}

}


*数组与Object的关系及其反射类型*

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;

非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。


Arrays.asList()方法处理int[]和String[]时的差异。

int[] arr =new int[] { 1, 2, 3 };
String[] str =newString[] {"黑马程序员", "黑马论坛", "CSDN社区"

// 通过Arrays.asList方法打印出集合的内容
System.out.println(Arrays.asList(arr));
// 结果:[[I@62bc184]

//原因是因为JDK1.4中为Arrays.asList(Object[] a),JDK1中
//Arrays.asList(T... a)。  arr是int[]类型,JDK1.4中的asList方
//法理不了,JDK1.5可以处理。但是JDK1.5将
//int数组整体作为一个参数进行处理。
// 因此最终结果就是将 int[]进行了封装,结果类型也就成了[[I。

System.out.println(Arrays.asList(str));
// 结果:[a, b, c]

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