黑马程序员---高新技术之反射

--------- android培训java培训、期待与您交流! ----------

 

 

黑马程序员---高新技术之反射

 

1.反射的基石---Class类

     class类是对对象的抽象,而Class是对class的抽象,或者说类是对对象的共性的描述,而Class又是对类的共性的描述,但它本身又是一个类,它的具体实例是内存中某个类的字节码。

     得到类的字节码的方式有三种:

     (1)对象.getClass();(2)类名.class;(3)Class.forName("完整类名“);

      Class.forName()的作用:如果有要获得的字节码存在于内存中就直接返回,如果不存在,则通过类加载器将其 .clas文件加载后返回。

       九种预定义的Class实例对象:表示八个基本类型和void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即boolean、byte、char、short、int、long、float 和double。

       数组的Class实例对象:类型[ ].class,可以用isArray()方法判断一个Class实例是否为数组。


反射就是把java类中的各种成分映射成java类

 

2.java类各个成分的相应的反射

(1)Construtcor类:得到某个类的所有构造方法:

       Constructor[] constructors=String.class.getConstructors();
       Constructor[] constructors=String.class.getDeclaredConstructors();//包括私有的
              得到某个类的某个构造方法:会用到参数类型的Class对象

        Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
	创建实例对象:参数要用获得构造方法时指定的类型。
	       普通方式:String str = new String(new StringBuffer("abc"));
       反射方式:String str1 =(String) constructor1.newInstance(new StringBuffer("abc"));


 

(2)Field类:类的成员变量,它的具体实例代表的的是类中某个字段的定义,而非具体的变量。

public class ReflectPoint{
   private int x;
   public  int y;
   public String str1 = "Master";
   public String str2 = "Basketball";
   public String str3 = "itcast";  

   public ReflectPoint(int x ,int y){
      super();
      this.x=x;
      this.y = y;
   }
}


 

 

应用案例:将RefectPoint中的所有String成员变量的值中的“a”,替换成“w”

private static void changeStringValue(Object obj) throws Exception {
		Field [] fields = obj.getClass().getFields();
		for(Field field:fields){
			if(field.getType()==String.class){//字节码的比较用==更精确
				String str =(String) field.get(obj);
				String str1 = str.replace('a','w');
				field.set(obj, str1);
				
			}
			
		}
	}


 

(3)Method类:代表某个类中的一个方法

String str = "abc";
Method methodCharAt = str.getClass().getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str, 2));//如果方法是静态的,invoke的第一次参数可以写成null
System.out.println(methodCharAt.invoke(str, new Object[]{2}));//JDK1.4的语法,封箱成Integer


 

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

  jdk1.4:public Object invoke(Object obj,Object[ ] args);用的是数组
  jdk1.5:public Object invoke(Object obj,Object... args);用的是可变参数

String startingClassName =args[0];//注意,要在该程序的运行环境中配置args为TestArguments; 
Method mainMethod =Class.forName(startingClassName).getMethod("main",String[].class);
//new Object[]{new String[]{"ball","wife"}
mainMethod.invoke(null,new Object[]{new String[]{"ball","wife"}});//这句为什么?JDK1.5向下兼容1.4版本,而1.4版本中,会把传递进的数组当一个个参数的组成的数组,而进行拆分。这句调用的是1.4的方法。
mainMethod.invoke(null,(Object)new String[]{"ball","wife"});//这句是调用了1.5的方法。

  

(4)数组的反射:如果两个数组的元素类型和维度相同,则它们用的是同一份字节码

 int[] a1 =new  int [3];
		int[] a2 = new int [4];
		int[][] a3 = new int[2][3];
		String[] a4 = new String[]{"111","222","333"};
		Class cl1 =a1.getClass();

		System.out.println(a1.getClass() == a2.getClass());//true;
//		System.out.println(a1.getClass() == a3.getClass());//MyEclipse会报错
//		System.out.println(a1.getClass() == a4.getClass());//MyEclipse会报错
		System.out.println("a1:"+a1.getClass().getName());
		System.out.println("a2:"+a2.getClass().getName());
		System.out.println("a3:"+a3.getClass().getName());
		System.out.println("a4:"+a4.getClass().getName());
		System.out.println(a1.getClass().getSuperclass().getName());
		System.out.println(a4.getClass().getSuperclass().getName());

               // Object[] obj1 = a1;//这句是错误的
                Object obj2 = a2;
                Object[] obj3 = a3;
                Object[] obj4 = a4;
//Arrays工具类,可以把数组当成集合来打印,但如果数组元素的类型是基本数据类型,那么打印的是数组引用的地址,而不是每个元素的值
                System.out.println(Arrays.asList(a1));
                System.out.println(Arrays.asList(a4));	


 

(5)反射的作用-->实现框架的功能

    框架与工具类的区别:工具类被用户的类调用,而框架则是调用用户提供的类。

    框架要解决的核心问题:因为在写框架时,你无法知道要调用的类名,所以无法直接new某个类的实例对象,而要用反射的方式来做了。

Collection collection= new ArrayList();//new HashSet();
	        ReflectPoint p1 = new ReflectPoint(4,4);
		ReflectPoint p2 = new ReflectPoint(2,5);
		ReflectPoint p3 = new ReflectPoint(7,6);
		ReflectPoint p4 = new ReflectPoint(4,4);
		
		collection.add(p1);
		collection.add(p2);
		collection.add(p3);
		collection.add(p1);
//重写ReflectPoint的hashCode和equals方法,让x和y参与其重新方法内。
/*
@Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + x;
  result = prime * result + y;
  return result;
 }
 @Override//如果把这句去掉,下边写成equals(ReflectPoint obj)不会报错
 public boolean equals(Object obj) {//Object不能改成ReflectPoint,否则就不是重写,而是重载了
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  ReflectPoint other = (ReflectPoint) obj;
  if (x != other.x)
   return false;
  if (y != other.y)
   return false;
  return true;
}
*/
                System.out.println(collection.size())//ArrayList值为4,HashSet则值为3;
		p1.y= 8;//HashSet集合中,p1元素的y参与了hashcode值的运算,所以改变y后,导致无法删除和重复加入该元素。
		System.out.println(collection.remove(p1));//ArrayList的remove 方法,删除列表中第一次出现的p1
		System.out.println(collection.size());//ArrayListz值减少一个为3,HashSet无法删除,所以值不变仍为3;


 

 

--------- android培训java培训、期待与您交流! ----------

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值