zoukankan      html  css  js  c++  java
  • Java基础(九)--反射

    什么是反射?

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

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

    反射的前提:

      需要获取代表每个类的java.lang.class对象,对于HotSpot来说,这个class对象保存在在方法区,作为这个类的各种数据的访问入口

    获取class对象的方式:

    public static void main(String[] args) throws Exception{
    	//第一种,通过对象获取class对象
    	A a = new A();
    	Class aClass = a.getClass();
    	System.out.println(aClass.getName());
    
    	//第二种,通过类直接获取class对象
    	Class aClass1 = A.class;
    	System.out.println(aClass == aClass1);
    
    	//第三种,通过类的全限定名获取class对象(包名+类名)
    	Class aClass2 = Class.forName("com.it.exception.A");
    	System.out.println(aClass == aClass2);
    }
    

    PS: 一般使用第三种方式来获取

    构造函数相关方法:

    public class A {
        public A(int i) {
            System.out.println("A Constructor " + i);
        }
    
        public A() {
            System.out.println("A Constructor No Parameter");
        }
    
        protected A(String name) {
            System.out.println("A Constructor " + name);
        }
    
        private A(int i, String name) {
            System.out.println("A Constructor " + i + " name " + name);
        }
    }
    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    
    	//返回所有public构造函数
    	Constructor[] constructors1 = aClass.getConstructors();
    	for (Constructor constructor : constructors1) {
    		System.out.println(constructor);
    	}
    	System.out.println("----getConstructors---------");
    	//返回具体某种参数类型的public构造函数,参数也可以是null,表示无参构造器
    	Constructor constructor = aClass.getConstructor(int.class);
    	System.out.println(constructor);
    	System.out.println("----get int Constructors---------");
    
    	//返回所有构造函数,无论什么修饰符修饰
    	Constructor[] constructors2 = aClass.getDeclaredConstructors();
    	for (Constructor constructor1 : constructors2) {
    		System.out.println(constructor1);
    	}
    	System.out.println("----getDeclaredConstructors---------");
    
    	//返回具体某种参数类型的构造函数,无论什么修饰符修饰
    	Constructor constructor2 = aClass.getDeclaredConstructor(String.class);
    	System.out.println(constructor2);
    	System.out.println("----String getDeclaredConstructor---------");
    }

    结果:

    public com.it.exception.A()
    public com.it.exception.A(int)
    ----getConstructors---------
    public com.it.exception.A(int)
    ----get int Constructors---------
    private com.it.exception.A(int,java.lang.String)
    protected com.it.exception.A(java.lang.String)
    public com.it.exception.A()
    public com.it.exception.A(int)
    ----getDeclaredConstructors---------
    protected com.it.exception.A(java.lang.String)
    

    getEnclosingConstructor:

    public class Outter {
        public void destination(String s) {
            class Inner1 {
                private String label;
                public Inner1() {
                    System.out.println("abc");
                }
                public Inner1(String whereTo) {
                    this.label = whereTo;
                }
            }
            Class aClass = new Inner1().getClass();
            //获取局部或匿名内部类在定义时所在的构造器
            System.out.println(aClass.getEnclosingConstructor());
        }
    
        public static void main(String[] args) {
            Outter outter = new Outter();
            outter.destination("aaa");
        }
    
    }
    

    这里实验类局部内部类一直得到的是null,大家可以试一下

    调用构造器:

    constructor.newInstance(); //默认无参构造器
    

    字段相关方法:

    public class A {
        private int id;
        private String name;
        public int sex;
    
    }
    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    	//获取所有public字段
    	Field[] fields = aClass.getFields();
    	for (Field field : fields) {
    		System.out.println(field);
    	}
    	//获取某个具体字段,这个字段必须是public修饰,否则会报错
    	Field field = aClass.getField("sex");
    	System.out.println(field);
    	//获取所有字段,无论修饰符
    	Field[] fields1 = aClass.getDeclaredFields();
    	for (Field field1 : fields1) {
    		System.out.println(field1);
    	}
    	//获取某个具体字段
    	Field field1 = aClass.getDeclaredField("id");
    	System.out.println(field1);
    }
    

    结果:

    public int com.it.exception.A.sex
    public int com.it.exception.A.sex
    private int com.it.exception.A.id
    private java.lang.String com.it.exception.A.name
    public int com.it.exception.A.sex
    private int com.it.exception.A.id
    

    其余操作:

    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    	Field field = aClass.getDeclaredField("name");
    	Object object = aClass.getDeclaredConstructor(null).newInstance();
    	field.setAccessible(true); //设置为true,private字段可以修改,私有字段必须设置为true,否则set字段会发生异常
    	field.set(object, "sam");//设置具体字段value
    	A a = (A)object;
    	System.out.println(a.toString());
    }
    

    结果:

    A(id=0, name=sam, sex=0)

    方法相关操作:

    public class A {
        private int id;
        private String name;
        public int sex;
    
        public void add() {
            System.out.println("add()");
        }
    
        private void del() {
            System.out.println("del()");
        }
    
        public static void update() {
            System.out.println("static update()");
        }
    }
    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    	Method[] methods = aClass.getMethods();
    	//获取所有public字段
    	for (Method method : methods) {
    		System.out.println(method);
    	}
    	//获取某个具体方法,这个method必须是public修饰,否则会报错
    	Method method = aClass.getMethod("add", null);
    	System.out.println(method);
    
    	//获取所有字段,无论修饰符
    	Method[] methods1 = aClass.getDeclaredMethods();
    	for (Method method1 : methods1) {
    		System.out.println(method1);
    	}
    
    	//获取某个具体字段
    	Method method1 = aClass.getDeclaredMethod("del", null);
    	System.out.println(method1);
    }
    

    结果:已经省略默认继承object的相关方法

    public void com.it.exception.A.add()
    public static void com.it.exception.A.update()
    
    public void com.it.exception.A.add()
    
    public void com.it.exception.A.add()
    public static void com.it.exception.A.update()
    private void com.it.exception.A.del()
    
    private void com.it.exception.A.del()
    

    其余操作:

    private int del(int i) {
    	System.out.println("del(): " + i);
    	return i + 3;
    }
    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    	Object object = aClass.getDeclaredConstructor(null).newInstance();
    	Method method = aClass.getDeclaredMethod("del", int.class);
    	method.setAccessible(true);
    	Object object1 = method.invoke(object, 20);
    	System.out.println(object1);
    }
    

    结果:

    del(): 20
    23
    

    其他:

    public class A extends B implements C{
    
        @Override
        public void f() throws IOException {
            System.out.println("f()");
        }
    }
    public static void main(String[] args) throws Exception{
    	Class aClass = Class.forName("com.it.exception.A");
    	System.out.println(aClass.getSuperclass());// 获取父类Class对象
    	System.out.println(aClass.getClassLoader());// 获取类的加载器
    	System.out.println(aClass.getInterfaces()[0]);// 获取类的接口数组列表
    
    	A[] as = new A[1];
    	System.out.println(as.getClass().getComponentType());// 获取该数组的Class对象
    
    	System.out.println(aClass.getPackage().getName());// 获取包
    }
    

    结果:

    class com.it.exception.B
    sun.misc.Launcher$AppClassLoader@18b4aac2
    interface com.it.exception.C
    class com.it.exception.A
    com.it.exception

    通过反射越过泛型检查

    public static void main(String[] args) throws Exception{
            ArrayList<String> list = new ArrayList<>();
            list.add("a");
            list.add("b");
    //        List<String> list = Arrays.asList("a", "b");
            Class aClass = list.getClass();
            Method method = aClass.getMethod("add", Object.class);
            method.invoke(list, 20);
            System.out.println(list);
    //        list.forEach(s -> {
    //            System.out.println(s);
    //        });
        }
    

    结果:List<String> list = Arrays.asList("a", "b");然后执行invoke()会报错的,也不要使用foreach也会报错(ClassCastException)

  • 相关阅读:
    DataSingleton单例
    iOS平台XML解析类库对比和安装说明
    ASIHTTPRequest类库简介和使用说明
    IOS开发之格式化日期时间
    iOS多线程编程之NSThread的使用
    Django的Xadmin后台集成富文本Ueditor
    Django DEBUG=False后静态文件加载失败
    Python多进程
    linux平台虚拟环境依赖安装
    SQLite基础使用
  • 原文地址:https://www.cnblogs.com/huigelaile/p/11022931.html
Copyright © 2011-2022 走看看