黑马程序员——高新技术——反射

 

反射技术:

  Java反射机制是在运行状态中,对应任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性

  这种动态获取信息以及动态调用对象的方法的功能称为:java的反射机制

反射:

  反射就是把Java类中的各种成分(变量、方法、构造方法、包)映射成相应的java类。

  获得这些信息的关键类是:Field、Method、Contructor、Package等。

  一个类中的每个成员都可以用相应的方法API类的一个实例对象来表示,通过调用Class类的

方法可以得到这些实例对象后有什么用呢?这就是学习和应用反射的要点。

 

第一讲  反射的应用场所

  • 1.Class概述
    • .class文件加载到内存中就是一个Class对象
    • 反射技术可以对类进行解剖
    • 获取Class对象的方式有3种:
      • Class.forName(类名);比如:Class.forName(“java.util.Date”)
      • 类名.class比如:System.class
      • 对象.getClass()比如:new person().getClass()

基本数据冷箱定义Clss是对象

参考:boolean   class.isPrimitive()方法判断是否

    比如:int.class==Integer.TYPE是对的

数组类型的Class实例对象

   boolean    Class.isArray():判断是否为数组

    总之,只有在源程序出现的类型,都有各自的Class实例对象,例如:int[]、void

 

实例运用Constructor

 1 //        new String(new StringBuffer("abc"));
 2         Constructor<String> con1=
 3                 String.class.getConstructor(StringBuffer.class);
 4         Constructor<?> con2=
 5                  Class.forName("java.lang.String").getConstructor(StringBuffer.class);
 6 //        上述两种方法是一样的,注意参数调用的写法
 7         
 8         String s1= con1.newInstance(new StringBuffer("abc"));
 9         String s2= (String) con2.newInstance(new StringBuffer("abc"));
10         System.out.println(s1/*.charAt(2)*/);
11 //        调用获得的方法时要用到上面想要参数的实例对象
  • Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象

实例操作Field和暴力反射:

 1 import java.lang.reflect.*;
 2 public class ReliectDemo2 {
 3     public static void main(String[] args) throws Exception{
 4         
 5         ReflectPoint pt1=new ReflectPoint(3, 5);
 6 //        使用Field关键字
 7         Field fielY=pt1.getClass().getField("y");
 8 //        fielY的值是多少呢?不是5。fielY不是对象身上的变量,而是类上的,要用它去实例对象对应pt1的值的方法
 9         System.out.println(fielY.get(pt1));//为5
10         Field fielX=pt1.getClass().getDeclaredField("x");
11 //        由于x是被私有的,所以使用暴力反射
12         fielX.setAccessible(true);
13         System.out.println(fielX.get(pt1));//为3
14     }
15 }
16 class ReflectPoint {
17     private int x;
18     public int y;
19     public ReflectPoint(int x, int y) {
20         super();
21         this.x = x;
22         this.y = y;
23     }    
24 }

将类中的成员变量字符替换(替换的方法replaceAll)

        changeString(pt1);
        System.out.println(pt1);
    }

    private static void changeString(Object obj)throws Exception {
        Field[] fields = obj.getClass().getFields();//得到全部的成分
        for(Field field:fields){
//            if(field.getType().equals(String.class))
            if(field.getType()==String.class){//判断是否是String类型
                String oldValue=(String)field.get(obj);//得到值并强转
                String newValue=oldValue.replaceAll("a", "b");
                field.set(obj, newValue);
            }
        }
    }
}
class ReflectPointx {
    private int x;
    public int y;
    public String aa="basbeasas";
    public String bb="basdahfgeasas";
    public String cc="baaxas";
    public String dd="xxxxasasas";
    public ReflectPointx(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    
    public String toString(){
        return aa+"--"+bb+"--"+cc+"--"+dd;
    }    
}

Mehod类是得到某个类的成员方法的类

1         String str="abc";
2         Method methodCharAt =
3                 String.class.getMethod("charAt", int.class);//得到String中charAt(int)方法
4         System.out.println(methodCharAt.invoke(str, 1));//给刚刚得到的方法赋予实际参数,答案是b
5         System.out.println(methodCharAt.invoke(str, new Object[]{2}));//旧的调用方法,答案是c

注:如果invoke(null,)的这里第一个参数数null。说明该Method对象的对应的是静态方法

 

Method方法:在用eclipse运行时,序Run as——RunConfigurations——Argument——Program arguments中添加执行的类名,在类名上按F2

 1 import java.lang.reflect.*;
 2 public class ReliectDemo2 {
 3     public static void main(String[] args) throws Exception{
 4 //        普通方法
 5 //        TestArgument.main(new String[]{"aaa","bbb","ccc"});
 6 //        使用反射的方法:不需要知道main方法所在的类名
 7         String className=args[0];
 8         Method mainMethod = Class.forName(className).getMethod("main", String[].class);
 9 //        方法1:将数组打包,变压器拆包后就是String【】类型的整体
10         mainMethod.invoke(null,new Object[]{new String[]{"aaa","bbb","ccc"}});
11 //        方法2:强转转换为超类Object,不用拆包
12 //        mainMethod.invoke(null,(Object)new String[]{"aaa","bbb","ccc"});
13         
14     }
15     
16 }
17 
18 class TestArgument{
19     public static void main(String[] args){
20         for(String arg:args){
21             System.out.println(arg);
22         }
23     }
24 }

 反射获得数据的实例:

 1 String[] a1=new String[]{"a","b","c"};
 2 //        打印集合数组
 3         printObject(a1);
 4 //        打印集合
 5         printObject("abc");
 6         }
 7 
 8     private static void printObject(Object obj) {
 9         Class<? extends Object> claz =obj.getClass();
10         if(claz.isArray()){
11             int len=Array.getLength(obj);//得到数组长度
12             for(int i=0;i<len;i++)
13             {
14                 System.out.println(Array.get(obj,i));//得到第i个数组
15             }
16         }else{
17             System.out.println(obj);
18         }

一个集合类的实例:

        Collection collection = new HashSet();
         ReflectP p1 = new  ReflectP(3,3);
         ReflectP p2 = new  ReflectP(4,2);
         ReflectP p3 = new  ReflectP(3,3);
        collection.add(p1);
        collection.add(p2);
        collection.add(p3);
        collection.add(p1);
        System.out.println(collection.size());//3个
//        复写了hashCode和equals之后
        System.out.println(collection.size());//一般而言,2个
//        内存溢出:程序消失了,依然占用内存
        p1.y=7;
        collection.remove(p1);
        System.out.println(collection.size());//移不走
        }
}

class ReflectP{
    private int x;
    public int y;
    public String str1 = "abc";
    public String str2 = "basdsbd";
    public String str3 = "afafsd";
    public ReflectP(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ReflectP other = (ReflectP) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
}

 

反射存在的作用和意义:实现框架的功能

*框架与框架要解决的核心问题:

  相对于做房子:搭建一个毛坯房(框架),固定好门、窗、等位子,用户根据这个基础上随意增添自己的喜好(类)

*框架要解决的核心问题:

  我们在搭建框架的时候,你这个用户可能还在上小学,还不好写程序。那我写得框架程序怎么能条用你以后写得类呢?

  因为在写框架程序时,无法知道被调用的类名的,所以,在程序中无法直接new某个类的实例对象i,而需要用反射。

*综合实例:

  1)先用new语句创建ArrayList和HashSet的实例对象。演示用eclipse自动生成ReflectPoint类的equals和hashCode方法

,比较两个集合的运行结果;

简单框架程序的步骤:

  1)右击项目File命名一个配置文件如:config:properties,写入配置信息:键值对形式:className = java.util.ArrayList

  2)代码实现:

    InputStream ips = new FileInputStream(“config:properties”);//读取配置文件

    Properties props = new Properties(); 

    Properties.load(ips);//加载这个配置信息;

    ips.close();

    String className = props.getProperty("className");//得到className对应的Valued就是ArrayList

    主题程序就能通过反射创建newInstance()

    执行主程序;

 1 InputStream ips = new FileInputStream("config.properties");
 2         Properties props = new Properties();
 3         props.load(ips);
 4         ips.close();
 5         
 6         String className = props.getProperty("className");//以后只要在配置文件改动就可以了
 7 //        反射机制
 8         Collection collections =
 9                 (Collection)Class.forName(className).newInstance();
10         
11 //        Collection collection = new HashSet();
12         ReflectP p1 = new  ReflectP(3,3);
13          ReflectP p2 = new  ReflectP(4,2);
14          ReflectP p3 = new  ReflectP(3,3);
15         collections.add(p1);
16         collections.add(p2);
17         collections.add(p3);
18         collections.add(p1);
19         System.out.println(collections.size());

配置文件:

className=java.util.ArrayList
classname2=java.util.HashSet

 

posted @ 2014-12-26 20:20  水の音  阅读(154)  评论(0编辑  收藏  举报