黑马程序员_java高新(二)_反射

时间:2023-02-19 17:18:54

---------------------- <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 类型(booleanbytecharshortintlongfloat 和double)和关键字void 也

 

 

表示为Class对象。基本类型的字节码获取方式只有一种就是类名.class。

 

 

Java代码  黑马程序员_java高新(二)_反射
  1. String str1 = "abc";  
  2.         Class cls1 = str1.getClass();  
  3.         Class cls2 = String.class;  
  4.         Class cls3 = null;  
  5.         try {  
  6.             cls3 = Class.forName("java.lang.String");  
  7.         } catch (ClassNotFoundException e) {  
  8.             e.printStackTrace();  
  9.         }  
  10.           
  11.         System.out.println(cls1 == cls2);//true  
  12.         System.out.println(cls1 == cls3);//true  
  13.         System.out.println(cls2 == cls3);//true  
  14.           
  15.         System.out.println(int.class == Integer.class);//false  
  16.         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代码  黑马程序员_java高新(二)_反射
  1. Constructor<String> con1 = String.class.getConstructor(StringBuffer.class);  
  2.         String str2 = con1.newInstance(new StringBuffer("abc"));  
  3.         System.out.println(str2.charAt(2));  

 

 

Field的反射:

 

 

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

 

Java代码  黑马程序员_java高新(二)_反射
  1. ReflectPoint pt1 = new ReflectPoint(3,5);  
  2.           
  3.         Field fieldY = pt1.getClass().getField("y");//获取公有的成员变量  
  4.           
  5.         System.out.println(fieldY.get(pt1));  
  6.           
  7.           
  8.         Field fieldX = pt1.getClass().getDeclaredField("x");//强行获取私有的成员变量  
  9.           
  10.         fieldX.setAccessible(true);//可以获取私有成员变量的值  
  11.           
  12.         System.out.println(fieldX.get(pt1));  

 

 

综合示例:

 

Java代码  黑马程序员_java高新(二)_反射
  1. private static void changeStringValue(Object obj) throws Exception {  
  2.           
  3.         Field[] fields = obj.getClass().getFields();//获取所有公有的成员变量  
  4.           
  5.         for(Field field : fields) {//遍历这些成员变量  
  6.               
  7.             if(field.getType() == String.class){//判断该变量的类型是不是String  
  8.                   
  9.                 String oldValue = (String)field.get(obj);  
  10.                   
  11.                 String newValue = oldValue.replace('b''a');//替换  
  12.                 field.set(obj, newValue);//设置新值  
  13.             }  
  14.         }  
  15.     }  
  16.   
  17. ReflectPoint类:  
  18.   
  19. public class ReflectPoint {  
  20.   
  21.     private int x;  
  22.       
  23.     public int y;  
  24.       
  25.     public String str1 = "ball";  
  26.       
  27.     public String str2 = "basketball";  
  28.       
  29.     public String str3 = "itcast";  
  30.   
  31.     public ReflectPoint(int x, int y) {  
  32.           
  33.         super();  
  34.           
  35.         this.x = x;  
  36.           
  37.         this.y = y;  
  38.     }  
  39.   
  40.     @Override  
  41.     public String toString() {  
  42.           
  43.         return str1+":"+str2+":"+str3;  
  44.     }  
  45.   
  46. }  

 

 

成员方法的反射(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代码  黑马程序员_java高新(二)_反射
  1. Method methodCharAt = String.class.getMethod("charAt"int.class);  
  2.           
  3.         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代码  黑马程序员_java高新(二)_反射
  1. main方法的调用:  
  2.         String startingClassName = args[0];  
  3.           
  4.         Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);  
  5.           
  6.     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代码  黑马程序员_java高新(二)_反射
  1. int [] a1 = new int[]{1,2,3};  
  2.         int [] a2 = new int[4];  
  3.         int[][] a3 = new int[2][3];  
  4.         String [] a4 = new String[]{"a","b","c"};  
  5.         System.out.println(a1.getClass() == a2.getClass());//true  
  6.         System.out.println(a1.getClass() == a4.getClass());//false  
  7.         System.out.println(a1.getClass() == a3.getClass());//false  
  8.         System.out.println(a1.getClass().getName());  
  9.         System.out.println(a1.getClass().getSuperclass().getName());  
  10.         System.out.println(a4.getClass().getSuperclass().getName());  

 

 

无法通过反射直接获得数组中元素的类型,但可以通过其中一个元素获得类型:

 

    a[0].getClass().getName();

 

 

Java代码  黑马程序员_java高新(二)_反射
  1. private static void printObject(Object obj) {  
  2.     Class clazz = obj.getClass();//获取obj的类型字节码  
  3.     if(clazz.isArray()){//判断是不是数组类型  
  4.         int len = Array.getLength(obj);//得到数组长度  
  5.         for(int i=0;i<len;i++){//遍历打印这个数组  
  6.             System.out.println(Array.get(obj, i));  
  7.         }  
  8.     }else{  
  9.         System.out.println(obj);//如果不是数组类型,则直接打印  
  10.     }  
  11.       
  12. }  

 

 

泛型的反射:

 

 

通过反射获取方法,再获得方法的参数列表的类型,获取其参数的实际类型。

 

 

Java代码  黑马程序员_java高新(二)_反射
  1. Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);  
  2.         Type[] types = applyMethod.getGenericParameterTypes();  
  3.         ParameterizedType pType = (ParameterizedType) types[0];  
  4.           
  5.         System.out.println(pType.getActualTypeArguments()[0]);  
  6.     }  
  7.       
  8.     public static void applyVector(Vector<Date> v1) {  
  9.           
  10.     }  

---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity开发</a>、<a href="http://www.itheima.com"target="blank">.Net培训</a>、期待与您交流! ----------------------