反射

声明一个对象,但是此对象需要实例化之后才能使用。

 

3.1 认识反射:

正常情况下,一个类要想使用,必须先找到这个类,然后才能创建对象,必须要先有类 再有对象。

public finalClass<?>  getClass();此可以方法返回一个class,通过class就可以完成反射的操作。

3.2.认识class类:

在反射机制中,class 是一个源头,所有的反射操作从此类展开,实例化Class类,可以通过下面的三种方式:

    通过Object类中的getClass()方法

    通过类.Class的形式

    通过Class.forName();//推荐使用的方式

 3.3通过Class类实例化对象:

              在class的使用中,实例化对象,是最常用的一种操作。而且日后所有框架的实现原理都是依靠Class来完成的。

3.3.1.实例化无参构造的类(最重要):

              package org.lxh.demo.classdemo02;

              public class Person {

                            public StringtoString(){

                                          return"hello World";

                            }

              }

              通常是通过关键字new来实例化对象,但是现在通过Class来完成。按照以下的步骤。

              1.根据包.类名称实例化class对象。

              2.通过Class类中的以下方法

                            public TnewInstance()

              throws InstantiationException,

                     IllegalAccessException

 

packageorg.lxh.demo.classdemo02;

public classInstanceDemo01 {

              public static void main(String[]args) {

                            Class<?>c  = null ;

                            try {

                                          c =Class.forName("org.lxh.demo.classdemo02.Person");

                            } catch(ClassNotFoundException e) {

                                          //TODO Auto-generated catch block

                                          e.printStackTrace();

                            }

                            try {

                                          Personp = (Person)c.newInstance();

                                          System.out.println(p);

                            } catch(InstantiationException e) {

                                          //TODO Auto-generated catch block

                                          e.printStackTrace();

                            } catch(IllegalAccessException e) {

                                          //TODO Auto-generated catch block

                                          e.printStackTrace();

                            }

              }

}

以上程序能正常实例化一个对象。

packageorg.lxh.demo.classdemo03;

public class Person{

              private String name;

              private int age;

             

              public Person(String name ,intage){

                            this.setName(name);

                            this.setAge(age);

              }

              public String toString(){

                            return "helloWorld";

              }

 

              public String getName() {

                            return name;

              }

 

              public void setName(String name) {

                            this.name = name;

              }

 

              public int getAge() {

                            return age;

              }

 

              public void setAge(int age) {

                            this.age = age;

              }

}

具有有参构造方法,这个程序因为没有无参构造方法,所以会报错

Exception in thread"main" java.lang.ClassCastException: org.lxh.demo.classdemo02.Person

              atorg.lxh.demo.classdemo03.InstanceDemo02.main(InstanceDemo02.java:14)

 

3.3.2实例化指定构造的类

以上的的操作中,必须存在一个无参的构造方法,而如果现在没有无参构造方法。则必须通过调用指定的构造方法,并向其传递参数,才可以实例化操作。

              public Constructor<?>[] getConstructors()--------------->获取一个类的所有的构造方法,以Constructor对象数组的形式返回。Constructor类的定义,Constructor类是在

              java.lang.reflect包中,所以是属于反射的操作包。取得一个构造方法后,可以通过Constructor的以下方法进行实例化:

              public T newInstance(Object...initargs)

              throws InstantiationException,

                     IllegalAccessException,

                     IllegalArgumentException,

                     InvocationTargetException

              例:调用有两个参数的构造方法(略),比较复杂

              为了开发的方便,一定要在类中定义无参构造方法。

3.4通过class取得完整结构:(了解)

通过class类中的很多方法可以轻易取得一个类中定义的全部构造方法,普通方法,常量、变量等等。现在假设有如下的类。

packageorg.lxh.demo.classdemo04;

interface Info{

              public static final String AUTHOR= "MLDN" ;

              public String getInfo();

              public String say(Stringname,String content);

              public void sayHello();

}

public class Personimplements Info{

              private String name;

              private int age;

              public Person(){

                           

              }

              public Person(String name){

                            this.setName(name);

              }

              public Person(String name ,intage){

                            this(name);

                            this.setAge(age);

              }

              public String getName() {

                            return name;

              }

              public void setName(String name) {

                            this.name = name;

              }

              public int getAge() {

                            return age;

              }

              public void setAge(int age) {

                            this.age = age;

              }

              public String toString(){

                            return "姓名:" + this.name + "年龄:"  +this.age;

              }

              public String getInfo() {

                            return "hellworld";

              }

              public String say(String name,String content) {

                            return "说了:" + content;

              }

              public void sayHello() {

                            System.out.println("hello-------->"+ AUTHOR) ;

              }

}

下面通过一系列的反射,完成操作。

3.4.1 取得继承的父类 

public Class<?super T> getSuperclass()

public classGetSuperClassDemo {

              public static void main(String[]args) throws ClassNotFoundException {

                            Class<?> c=Class.forName("org.lxh.classDemo04.Person");

                            Class<?> sc =c.getSuperclass();

                            System.out.println(sc.getName());

              }

}

3.4.1 取得继承的父类

       publicstaticvoid main(String[] args) throws Exception {

              Class<?> c = Class.forName("org.lxh.demo.classdemo04.Person");

              Class<?> sc = c.getSuperclass() ;

              System.out.println(sc.getName());

       }

}

3.4.2 取得实现的全部接口

一个类可以实现多个接口,故有下列方法:

public Class<?>[] getInterfaces()
接口本身是一个特殊的类:所以会以Class的对象数组形式返回。

package org.lxh.demo.classdemo04;

publicclass GetInterfacesDemo {

       publicstaticvoid main(String[] args) throws Exception {

              Class<?> c = Class.forName("org.lxh.demo.classdemo04.Person");

              Class<?> Inter[] = c.getInterfaces() ;

              for(int i=0 ;i<Inter.length;i++){

                     System.out.println(Inter[i].getName());

              }

       }

}

3.4.3 取得类的全部构造方法

package org.lxh.demo.classdemo04;

 

import java.lang.reflect.Constructor;

 

publicclass GetConstructorDemo01 {

 

       publicstaticvoid main(String[] args) throws Exception {

              Class<?> c = Class.forName("org.lxh.demo.classdemo04.Person");

              Constructor<?>con[] = c.getConstructors(); // 得到全部构造

              for (int i = 0; i < con.length; i++) {

                     System.out.println(con[i].getName()); // 输出内容

              }

       }

}

以上确实得到了全部的构造方法,但是程序有一个弊病,如果用.getName()来取得,只能取得构造方法的名字,而访问的修饰符和参数全都不见了。

如果现在想手工拼凑出一个构造方法,还需要下面几个方法的支持。

1.       得到访问权限(修饰符)public int getModifiers()

2. 得到全部的参数。public Class<?>[] getParameterTypes()

从结果中发现,访问修饰符是数字,而不是之前看到的public,在程序开放中,访问权限基本上是以数字来表示的。如果要想正确还原一个方法的访问修饰符,则要用到Modifier类。

进行还原。public static String toString(int mod)

3.4.4 取得类的全部方法

public Method[] getMethods()
                    throws SecurityException

 

Class<?> c = Class.forName("org.lxh.demo.classdemo04.Person");

              Method m[] = c.getMethods(); // 取得全部的方法

              for (int i = 0; i < m.length; i++) {

                     System.out.println(m[i]); // 输出内容

以上是取得一个类中全部方法最简单的操作,但是与构造方法一样,可以通过反射机制慢慢取得,此时需要以下方法的支持。

1.取得一个方法的返回值类型,public Class<?> getReturnType()
2.取得方法的全部参数 public Class<?>[] getParameterTypes()
3.取得抛出的异常的类型。public Class<?>[] getExceptionTypes()

3.4.5 取得类的全部属性

1.得到继承而来的公共属性:public Field[] getFields()
                  throws SecurityException
2.得到自定义的属性:public Method[] getDeclaredMethods()
                            throws SecurityException
开发工具的核心原理就是反射。但是此种操作,一般不用。
 
 

3.5反射的进一步应用(理解)

3.5.1通过反射调用类中的方法

正常情况下,都是通过对象.方法完成类中指定方法的调用,那么实际上可以通过反射机制完成类中方法的调用。

在Class类中用如下方法来取得要调用方法的method对象:public Method getMethod(String name,
                        Class<?>... parameterTypes)
                 throws NoSuchMethodException,
                        SecurityException
之所以要传递可变参数,主要是因为一个方法在使用的时候可能存在多个调用的参数,所以在此处必须指定好参数的类型。
取得method对象之后,通过如下方法 进行调用:
public Object invoke(Object obj,
                     Object... args)
              throws IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException
以上方法表示在程序中真正要执行的方法。

3.5.2通过反射直接操作类中的setter和getter

3.5.3通过反射直接操作属性

 

 
 
 
 
 

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值