java反射

来源:互联网 发布:eia数据对黄金的影响 编辑:程序博客网 时间:2024/05/22 17:50

一切皆对象

在Java中所有东西都是对象,只排除两个

  1. 普通数据类型
  2. 静态成员,是属于class的

类是对象,是Java.lang.Class类的实例对象

package reflect;    public class Test {        public static void main(String []args){            //A类的实例对象如何表示            A a=new A();//a就是A类的实例对象            //A类也是一个实例对象,是java.lang.Class的实例对象            //Class类的实例对象表示方法,3种            //第一种,实际告诉我们任何类都有个一隐含的静态成员变量class            Class c1=A.class;            //第二种,通过该类的实例对象            Class c2=a.getClass();            /*官网c1,c2表示了A类的类类型(class Type)             * 万事万物皆对象             * 类也是对象,是Class类的实例对象             * 我们称这个对象为该类的类类型             */            //不管c1、c2都代表了A类的类类型,一个类只可能是Class类的一个实例对象            System.out.println(c1==c2);            //第三种,            Class c3=null;            try {                c3=Class.forName("reflect.A");//需要有无参的构造方法            } catch (ClassNotFoundException e) {                e.printStackTrace();            }            System.out.println(c2==c3);            //我们可以通过类的类类型来创建该类的实例对象            try {                A a1=(A) c1.newInstance();                a1.print();            } catch (InstantiationException | IllegalAccessException e) {                e.printStackTrace();            }        }    }    class A{        public void print(){            System.out.println("print......");        }    }

java.lang.Class实例对象的三种表示方法

  1. 类名.class

    Class c1=A.class();
  2. 类的实例化对象.getClass()

    Class c2=a.getClass();
  3. Class.forName(“类的名称”),需要有无参的构造方法

    Class c3=Class.forName("reflect.A")

通过类的类类型创建该类的实例化对象

//我们可以通过类的类类型来创建该类的实例对象try {    A a1=(A) c1.newInstance();    a1.print();} catch (InstantiationException | IllegalAccessException e) {    e.printStackTrace();}

动态加载类

Class.for.Name(“类的全称”),不仅表示了该类的类类型,还表示了动态加载类

编译时加载的类是静态加载类,运行时加载的类是动态加载类

new创建的对象都是静态加载类,在编译时刻就需要加载所有可能使用到的类

获取类的详细信息

将类的方法详细信息输出

public class ClassUtils {    public static void printClassMessage(Object object){        //要获取类的信息,首先要获取类的类类型        Class c=object.getClass();//传递的是哪个子类的对象,就生成哪个子类的类类型        System.out.println("类的名称是:"+c.getName());        /*         * 一个成员方法,就是一个Method类对象         * getMethods()方法获取所有的public方法,包括从父类继承来的         * getDeclaredMethods()获取该类自己声明的方法,不管访问权限         */        Method[] ms=c.getMethods();        for (int i = 0; i < ms.length; i++) {            //得到方法返回值类型的类类型            Class returnType=ms[i].getReturnType();            System.out.print(returnType.getName()+" ");            //获取方法的名称            System.out.print(ms[i].getName()+"(");            //得到参数类型,得到的是参数列表类型的类类型            Class []paramTypes=ms[i].getParameterTypes();            for (Class class1 : paramTypes) {                System.out.print(class1.getName());            }            System.out.println(")");        }    }}

方法的反射

方法的反射:利用方法对象来调用方法。m.invoke(类对象,参数)

//获取类B的print方法,获取print方法就是获取类的信息,所以首先得获取类的类类型B b=new B();Class c=b.getClass();try {    //Method mq=c.getMethod("print", new Class[]{String.class});    Method m=c.getMethod("print", String.class);    //方法的反射操作,就是用方法对象来调用方法    m.invoke(b, "aaaaaaaaa");} catch (Exception e) {    e.printStackTrace();}

了解泛型的本质

泛型是为了在编译阶段保证数据的类型正确。如ArrayList list=new ArrayList();list集合中只能放入String类型的数据,如果放入不正确的类型将会报错

反射的操作都是在编译之后

public class demo3 {
public static void main(String[]args){
ArrayList list1=new ArrayList();
list1.add(“d”);
ArrayList list2=new ArrayList();
//list2.add(1);//会报错
//返回true,证明了编译后的集合泛型是去泛型化的
System.out.println(list1.getClass()==list2.getClass());

    //证明:用方法的反射,将整形数据放入list2中    try {        Method m=list2.getClass().getMethod("add", Object.class);        m.invoke(list2, 3);        //返回值为1,证明整型数据插入成功        System.out.println(list2.size());    } catch (Exception e) {        e.printStackTrace();    }}

}

0 0
原创粉丝点击