---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------
Class类:
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
得到各个字节码对应的实例对象的方法:( Class类型):
1、类名.class。
例如,System.class
2、对象.getClass()。
例如,new Date().getClass()
3、Class.forName("类名")。
例如,Class.forName("java.util.Date");
.class和Class.forName的区别:
后者可以在不确定要获得字节码的具体类的时候使用,传入的是一个字符串,经常在框架中使用。
九个预定义类型的实例对象:
基本的 Java 类型(boolean
、byte
、char
、short
、int
、long
、float
和double
)和关键字void
也
表示为Class
对象。基本类型的字节码获取方式只有一种就是类名.class。
Java代码
- String str1 = "abc";
- Class cls1 = str1.getClass();
- Class cls2 = String.class;
- Class cls3 = null;
- try {
- cls3 = Class.forName("java.lang.String");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- System.out.println(cls1 == cls2);//true
- System.out.println(cls1 == cls3);//true
- System.out.println(cls2 == cls3);//true
- System.out.println(int.class == Integer.class);//false
- System.out.println(int.class == Integer.TYPE);//true
反射:
反射就是把Java类中的各种成分映射成相应的java类。
构造方法的反射:
onstructor类代表某个类中的一个构造方法;
得到某个类所有的构造方法:
例子:
Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
例子:
Constructor constructor=Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
获得方法时要用到类型:
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
调用获得的方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。也就是使用String类的无参构造
方法创建了一个String对象。
以下是用参数为StringBuffer类型的构造函数创建一个String类型的实例对象:
Java代码
- Constructor<String> con1 = String.class.getConstructor(StringBuffer.class);
- String str2 = con1.newInstance(new StringBuffer("abc"));
- System.out.println(str2.charAt(2));
Field的反射:
Field类代表某个类中的一个成员变量。
Java代码
- ReflectPoint pt1 = new ReflectPoint(3,5);
- Field fieldY = pt1.getClass().getField("y");//获取公有的成员变量
- System.out.println(fieldY.get(pt1));
- Field fieldX = pt1.getClass().getDeclaredField("x");//强行获取私有的成员变量
- fieldX.setAccessible(true);//可以获取私有成员变量的值
- System.out.println(fieldX.get(pt1));
综合示例:
Java代码
- private static void changeStringValue(Object obj) throws Exception {
- Field[] fields = obj.getClass().getFields();//获取所有公有的成员变量
- for(Field field : fields) {//遍历这些成员变量
- if(field.getType() == String.class){//判断该变量的类型是不是String
- String oldValue = (String)field.get(obj);
- String newValue = oldValue.replace('b', 'a');//替换
- field.set(obj, newValue);//设置新值
- }
- }
- }
- ReflectPoint类:
- public class ReflectPoint {
- private int x;
- public int y;
- public String str1 = "ball";
- public String str2 = "basketball";
- public String str3 = "itcast";
- public ReflectPoint(int x, int y) {
- super();
- this.x = x;
- this.y = y;
- }
- @Override
- public String toString() {
- return str1+":"+str2+":"+str3;
- }
- }
成员方法的反射(Method):
Method类代表某个类中的一个成员方法。
得到类中的某一个方法:
例子:
Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式: System.out.println(charAt.invoke(str, 1));
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法!
Java代码
- Method methodCharAt = String.class.getMethod("charAt", int.class);
- System.out.println(methodCharAt.invoke(str1, 1));
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object... args) 可变参数;
Jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的语法,需要将一个数组作为参数
传递给invoke方法,数组中的每个元素分别对应被调用方法中的一个参数。
Java代码
- main方法的调用:
- String startingClassName = args[0];
- Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
- mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
为了兼容1.4版本没有可变参数方法,传入的一个数组对象会被自动拆包,变为多个参数,因此要打包成
一个Object对象传入,避免被拆包。
数组的反射:
1、具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
2、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
3、基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维
数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
Java代码
- int [] a1 = new int[]{1,2,3};
- int [] a2 = new int[4];
- int[][] a3 = new int[2][3];
- String [] a4 = new String[]{"a","b","c"};
- System.out.println(a1.getClass() == a2.getClass());//true
- System.out.println(a1.getClass() == a4.getClass());//false
- System.out.println(a1.getClass() == a3.getClass());//false
- System.out.println(a1.getClass().getName());
- System.out.println(a1.getClass().getSuperclass().getName());
- System.out.println(a4.getClass().getSuperclass().getName());
无法通过反射直接获得数组中元素的类型,但可以通过其中一个元素获得类型:
a[0].getClass().getName();
Java代码
- private static void printObject(Object obj) {
- Class clazz = obj.getClass();//获取obj的类型字节码
- if(clazz.isArray()){//判断是不是数组类型
- int len = Array.getLength(obj);//得到数组长度
- for(int i=0;i<len;i++){//遍历打印这个数组
- System.out.println(Array.get(obj, i));
- }
- }else{
- System.out.println(obj);//如果不是数组类型,则直接打印
- }
- }
泛型的反射:
通过反射获取方法,再获得方法的参数列表的类型,获取其参数的实际类型。
Java代码
- Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
- Type[] types = applyMethod.getGenericParameterTypes();
- ParameterizedType pType = (ParameterizedType) types[0];
- System.out.println(pType.getActualTypeArguments()[0]);
- }
- public static void applyVector(Vector<Date> v1) {
- }
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------