黑马程序员——反射

来源:互联网 发布:中国白银集团淘宝店 编辑:程序博客网 时间:2024/05/21 10:57

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

                                            反射

反射?
    
    问题1:
         class A{}
         class B extends A{
              void t(){}
         }


         A a = new B();
         a.t();   // 编译报错, 编译器在编译的时候会到编译类型A中去找是否有t方法
         // a 真正类型就是 B 类型 希望调用t  方法  --> 强制转换
         // 强制转换 : 引用类型 父类类型的变量 -- > 子类类型
         //          : 强转之前应该先判断类型
         Object o = new String("123");
         A a = (A)o;   // 编译OK ,运行报错
         判断类型 :
             ① o instanceof A;
             ② getClass()     // 就使用到了反射


    问题2 eclipse 中的Outline功能
    
    问题3 从面相对象的角度去思考


            JAVA反射机制是在运行状态中,对于任意一个,都能够知道

这个类的所有属性和方法;对于任意一个对象,都能够调用它的任

意一个方法和属性;这种动态获取的信息以及动态调用对象的方法

的功能称为java语言的反射机制。

       通俗来讲,反射就是利用已知类型的字节码文件,来获取该类

型的内部结构,比如里面的字段,方法,构造方法等等。

        我们用java中已有的类,String来做事例。

         String s1 = "1234";

         String  s2 = "abc";

         String s3 = "字符";

        s1,s2,s3都是一个对象,都是String类型的。我们在学继承的

时候有泛化这样一个概念,就是子类不断的向上抽取共有数据的

过程,叫做泛化。不同的类型向上抽取形成Class类,(注意:首字

母是大些的)。这样一个类就是反射类。

     反射 :


    通过反射区获得一个类(这样的结构) 的内部的结构  : 字段  方法

  构造方法


             * 1获得构造方法   -->  创建对象


     * 2获得方法          -->  执行 调用某个对象 的方法


     * 3 字段                 -->  获取值 或者是取值


      上面的三个对象上都可以设置取消检查java 访问修饰符权限的

能力      -->    操作 私有的成员

         反射就是一个暴力分子,他改变了java的运行规则。可以破

坏java运行规则,是 一把双刃剑。



上图中,不同的对象对应不同的类型,类中有字段方法构造方

法,我们将不同的类型的成员不断向上抽取,形成一个Class类

在Class类中有一个Field字段,用于存储对象的字段,用Method字

段存储对象的各种方法,用Constructor存储对象的构造方法,在

提供不同的方法访问这些对象里面的字段,方法,和构造方法


Class类

Class 类的实例表示正在运行的 Java 应用程序中的类和接

口。枚举是一种类,注释是一种接口。  字节码对象 (同一个类在

运行过程中字节码对象只有一份)

每个数组属于被映射为 Class 对象的一个类,所有具有相同

元素类型和维数的数组都共享该 Class 对象。

基本的 Java 类型(boolean、byte、char、short、int、

long、float 和 double)和关键字 void 也表示为 Class 对象

// 创建Class的对象  -- 类和接口

① Class 类中有一个静态的方法

                         static Class<?> forName(String className)

 返回与带有给定字符串名的类或接口相关联的 Class 对象 

 className - 所需类的完全限定名

② 类型名.class


③ 对象来获取 getClass

    // 2 获得数组的 Class 对象


            ② 类名.class


       ③ 对象来获取 getClass

// 3 9中预定义的类型的Class 对象


① 类型名.class


② 通过基本类型的包装类的字段(全局常量) 来获得 

                                    例如 : static Class<Integer> TYPE 表示基

本类型 int 的 Class 实例

     public static void main(String[] args) throws ClassNotFoundException {
// 3 9中预定义的类型的Class 对象
Class c1 = Class.forName("int");
System.out.println(c1);
Class c2 = int.class;
Class c3 = Integer.TYPE;
System.out.println(c2 == c3);  // true

Class c4 = Integer.class;
System.out.println(c2 == c4);  // false

System.out.println(void.class == Void.TYPE)

Class clz1 = Class.forName("java.lang.String");
Class clz2 = String.class;
Class clz3 = "".getClass();//   "haha".getClass();

System.out.println(clz1);
System.out.println(clz1 == clz2);  // true
System.out.println(clz1 == clz3);  // true
// 从上述事例中说明 多种方式获得的字节码对象是同一份

//=========数组
//每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
String[] s = new String[]{"12","sv"};
String[] ss = new String[]{"12","sv","",""};
Class s1 = Class.forName("java.lang.String[]");   // 不能这样写
Class s2 = String[].class;
Class s3 = s.getClass();
System.out.println(s2);
System.out.println(s2 == s3);

System.out.println(new String[10].getClass()  == new String[1].getClass());  //  true

Class cs = new String[10].getClass();
Class ci = new Integer[1].getClass();
System.out.println(cs == ci);  // false
String[] sss={};
String[][] ssss={};
Class c3 = sss.getClass();
Class c4 = ssss.getClass();
System.out.println(c3 == c4);

1 验证类中 的默认的无参数的构造方法是否存在
* a 先获得类的字节码对象
* b 通过字节码对象 调用其获得构造方法的方法

* Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 
* parameterTypes : 就是构造方法中参数类型的 Class 对象
  Constructor<?>[] getConstructors()  获得所有的公共的构造方法
   
  Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 
  Constructor<?>[] getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 


类成员:  构造方法   字段  方法
   Class 中获得字段  方法 的方法  和上面获得构造的方法的方法设计上很类似
设计示例代码 验证Class 中获得方法  的方法

// 只能找公共的,所有父类, 实现的接口中公共
Method  getMethod(String name,Class<?>... parameterTypes)
Method[] getMethods();

//只能找到本类中所有自己定义的方法,和访问权限无关
Method  getDeclaredMethod(String name,Class<?>... parameterTypes)
Method[] getDeclaredMethods();

*/
public static void main(String[] args)  {
Class<Person> c = Person.class;
// Constructor[] cs = c.getConstructors();   // 只能获得公共的
Constructor[] cs = c.getDeclaredConstructors();   // 只能获得公共的
for (Constructor constructor : cs) {
System.out.println(constructor);
}

// 获得一个构造器对象  有什么用?  可以创建对象
// Constructor 的方法    T newInstance(Object... initargs) 
//Person p = new Person();   // 不能访问私有的成员
Constructor<Person> cp = cs[0];
// 设置此构造器对象失去 检查java语法访问控制能力
cp.setAccessible(true);
//创建Person实例,利用Constructor的newInstance方法
// Person p = cp.newInstance();
Constructor<Person>  cc = c.getDeclaredConstructor(String.class,int.class);
System.out.println(cc);

Person o = c.newInstance();
System.out.println(o);
}
}

getConstructor()  只能获取公共构造方法,可以根据指定参数获取

getConstructors()  只能获取公共构造方法(所有的)

getDelclaredConstructor() 获取构造方法,根据指定参数获取(与访问修饰符无关)

getDelclaredConstructors() 获取所有构造方法与访问修饰符无关)

getMethod() 获取公共方法,根据指定参数获取(可以获取实现接口,继承父类的公共方法)

getMethods() 获取公共方法,(获取能实现接口,继承父类的公共方法)

getDelclaredMethod() 获取方法,根据指定参数获取(只能获取本类中方法,与访问修饰符无关)

getDelclaredMethods() 获取方法(只能获取本类中所有方法,与访问修饰符无关)


点击打开链接 点击打开链接 点击打开链接 <a href="target=" _xhe_href="target=" blank"="">.Net培训、期待与您交流!">点击打开链接 点击打开链接

0 0
原创粉丝点击