反射 订阅
反射是一种计算机处理方式。有程序可以访问、检测和修改它本身状态或行为的这种能力。能提供封装程序集、类型的对象。(程序集包含模块,而模块包含类型,类型又包含成员。) 展开全文
反射是一种计算机处理方式。有程序可以访问、检测和修改它本身状态或行为的这种能力。能提供封装程序集、类型的对象。(程序集包含模块,而模块包含类型,类型又包含成员。)
信息
性    质
计算机术语
应用领域
软件工程
外文名
reflection
中文名
反射
基本释义
提供封装程序集、类型的对象
反射用途
您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。1.使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。2.使用 Module 了解如下的类似信息:包含模块的程序集以及模块中的类等。您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。3.使用 ConstructorInfo 了解如下的类似信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。4.使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。5.使用 MethodInfo 来了解如下的类似信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信 息(如 abstract 或 virtual)等。使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。6.使用 FieldInfo 来了解如下的类似信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。7.使用 EventInfo 来了解如下的类似信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。8.使用 PropertyInfo 来了解如下的类似信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。9.使用 ParameterInfo 来了解如下的类似信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。
收起全文
精华内容
下载资源
问答
  • Java基础之—反射(非常重要)

    万次阅读 多人点赞 2017-05-13 13:29:02
    反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一、反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法...

    反射是框架设计的灵魂

    (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

    一、反射的概述

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.


    以上的总结就是什么是反射
    反射就是把java类中的各种成分映射成一个个的Java对象
    例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
         (其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
    如图是类的正常加载过程:反射的原理在与class对象。
    熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。



    其中这个Class对象很特殊。我们先了解一下这个Class类

    二、查看Class类在java中的api详解(1.7的API

    如何阅读java中的api详见java基础之——String字符串处理



    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
    Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。

    没有公共的构造方法,方法共有64个太多了。下面用到哪个就详解哪个吧



    三、反射的使用(这里使用Student类做演示)

    先写一个Student类。

    1、获取Class对象的三种方式

    1.1 Object ——> getClass();
    1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
    1.3 通过Class类的静态方法:forName(String  className)(常用)


    其中1.1是因为Object类中的getClass方法、因为所有类都继承Object类。从而调用Object类来获取


    package fanshe;
    /**
     * 获取Class对象的三种方式
     * 1 Object ——> getClass();
     * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
     * 3 通过Class类的静态方法:forName(String  className)(常用)
     *
     */
    public class Fanshe {
    	public static void main(String[] args) {
    		//第一种方式获取Class对象  
    		Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
    		Class stuClass = stu1.getClass();//获取Class对象
    		System.out.println(stuClass.getName());
    		
    		//第二种方式获取Class对象
    		Class stuClass2 = Student.class;
    		System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
    		
    		//第三种方式获取Class对象
    		try {
    			Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
    			System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		}
    		
    	}
    }

    注意:在运行期间,一个类,只有一个Class对象产生。

    三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。

    2、通过反射获取构造方法并使用:

    student类:
    package fanshe;
    
    public class Student {
    	
    	//---------------构造方法-------------------
    	//(默认的构造方法)
    	Student(String str){
    		System.out.println("(默认)的构造方法 s = " + str);
    	}
    	
    	//无参构造方法
    	public Student(){
    		System.out.println("调用了公有、无参构造方法执行了。。。");
    	}
    	
    	//有一个参数的构造方法
    	public Student(char name){
    		System.out.println("姓名:" + name);
    	}
    	
    	//有多个参数的构造方法
    	public Student(String name ,int age){
    		System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
    	}
    	
    	//受保护的构造方法
    	protected Student(boolean n){
    		System.out.println("受保护的构造方法 n = " + n);
    	}
    	
    	//私有构造方法
    	private Student(int age){
    		System.out.println("私有的构造方法   年龄:"+ age);
    	}
    
    }
    

    共有6个构造方法;

    测试类:
    package fanshe;
    
    import java.lang.reflect.Constructor;
    
    
    /*
     * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
     * 
     * 1.获取构造方法:
     * 		1).批量的方法:
     * 			public Constructor[] getConstructors():所有"公有的"构造方法
                public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
         
     * 		2).获取单个的方法,并调用:
     * 			public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
     * 			public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
     * 		
     * 			调用构造方法:
     * 			Constructor-->newInstance(Object... initargs)
     */
    public class Constructors {
    
    	public static void main(String[] args) throws Exception {
    		//1.加载Class对象
    		Class clazz = Class.forName("fanshe.Student");
    		
    		
    		//2.获取所有公有构造方法
    		System.out.println("**********************所有公有构造方法*********************************");
    		Constructor[] conArray = clazz.getConstructors();
    		for(Constructor c : conArray){
    			System.out.println(c);
    		}
    		
    		
    		System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
    		conArray = clazz.getDeclaredConstructors();
    		for(Constructor c : conArray){
    			System.out.println(c);
    		}
    		
    		System.out.println("*****************获取公有、无参的构造方法*******************************");
    		Constructor con = clazz.getConstructor(null);
    		//1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
    		//2>、返回的是描述这个无参构造函数的类对象。
    	
    		System.out.println("con = " + con);
    		//调用构造方法
    		Object obj = con.newInstance();
    	//	System.out.println("obj = " + obj);
    	//	Student stu = (Student)obj;
    		
    		System.out.println("******************获取私有构造方法,并调用*******************************");
    		con = clazz.getDeclaredConstructor(char.class);
    		System.out.println(con);
    		//调用构造方法
    		con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
    		obj = con.newInstance('男');
    	}
    	
    }
    

    后台输出:
    **********************所有公有构造方法*********************************
    public fanshe.Student(java.lang.String,int)
    public fanshe.Student(char)
    public fanshe.Student()
    ************所有的构造方法(包括:私有、受保护、默认、公有)***************
    private fanshe.Student(int)
    protected fanshe.Student(boolean)
    public fanshe.Student(java.lang.String,int)
    public fanshe.Student(char)
    public fanshe.Student()
    fanshe.Student(java.lang.String)
    *****************获取公有、无参的构造方法*******************************
    con = public fanshe.Student()
    调用了公有、无参构造方法执行了。。。
    ******************获取私有构造方法,并调用*******************************
    public fanshe.Student(char)
    姓名:男

    调用方法:
    1.获取构造方法:
      1).批量的方法:
    public Constructor[] getConstructors():所有"公有的"构造方法
                public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
         
      2).获取单个的方法,并调用:
    public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
    public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;

      调用构造方法:
    Constructor-->newInstance(Object... initargs)

    2、newInstance是 Constructor类的方法(管理构造函数的类)
    api的解释为:
    newInstance(Object... initargs)
               使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
    它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用

    3、获取成员变量并调用

    student类:
    package fanshe.field;
    
    public class Student {
    	public Student(){
    		
    	}
    	//**********字段*************//
    	public String name;
    	protected int age;
    	char sex;
    	private String phoneNum;
    	
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", sex=" + sex
    				+ ", phoneNum=" + phoneNum + "]";
    	}
    	
    	
    }


    测试类:
    package fanshe.field;
    import java.lang.reflect.Field;
    /*
     * 获取成员变量并调用:
     * 
     * 1.批量的
     * 		1).Field[] getFields():获取所有的"公有字段"
     * 		2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
     * 2.获取单个的:
     * 		1).public Field getField(String fieldName):获取某个"公有的"字段;
     * 		2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
     * 
     * 	 设置字段的值:
     * 		Field --> public void set(Object obj,Object value):
     * 					参数说明:
     * 					1.obj:要设置的字段所在的对象;
     * 					2.value:要为字段设置的值;
     * 
     */
    public class Fields {
    
    		public static void main(String[] args) throws Exception {
    			//1.获取Class对象
    			Class stuClass = Class.forName("fanshe.field.Student");
    			//2.获取字段
    			System.out.println("************获取所有公有的字段********************");
    			Field[] fieldArray = stuClass.getFields();
    			for(Field f : fieldArray){
    				System.out.println(f);
    			}
    			System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
    			fieldArray = stuClass.getDeclaredFields();
    			for(Field f : fieldArray){
    				System.out.println(f);
    			}
    			System.out.println("*************获取公有字段**并调用***********************************");
    			Field f = stuClass.getField("name");
    			System.out.println(f);
    			//获取一个对象
    			Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();
    			//为字段设置值
    			f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"
    			//验证
    			Student stu = (Student)obj;
    			System.out.println("验证姓名:" + stu.name);
    			
    			
    			System.out.println("**************获取私有字段****并调用********************************");
    			f = stuClass.getDeclaredField("phoneNum");
    			System.out.println(f);
    			f.setAccessible(true);//暴力反射,解除私有限定
    			f.set(obj, "18888889999");
    			System.out.println("验证电话:" + stu);
    			
    		}
    	}
    

    后台输出:

    ************获取所有公有的字段********************
    public java.lang.String fanshe.field.Student.name
    ************获取所有的字段(包括私有、受保护、默认的)********************
    public java.lang.String fanshe.field.Student.name
    protected int fanshe.field.Student.age
    char fanshe.field.Student.sex
    private java.lang.String fanshe.field.Student.phoneNum
    *************获取公有字段**并调用***********************************
    public java.lang.String fanshe.field.Student.name
    验证姓名:刘德华
    **************获取私有字段****并调用********************************
    private java.lang.String fanshe.field.Student.phoneNum
    验证电话:Student [name=刘德华, age=0, sex=

    由此可见
    调用字段时:需要传递两个参数:
    Object obj = stuClass.getConstructor().newInstance();//产生Student对象--》Student stu = new Student();
    //为字段设置值
    f.set(obj, "刘德华");//为Student对象中的name属性赋值--》stu.name = "刘德华"
    第一个参数:要传入设置的对象,第二个参数:要传入实参

    4、获取成员方法并调用

    student类:
    package fanshe.method;
    
    public class Student {
    	//**************成员方法***************//
    	public void show1(String s){
    		System.out.println("调用了:公有的,String参数的show1(): s = " + s);
    	}
    	protected void show2(){
    		System.out.println("调用了:受保护的,无参的show2()");
    	}
    	void show3(){
    		System.out.println("调用了:默认的,无参的show3()");
    	}
    	private String show4(int age){
    		System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
    		return "abcd";
    	}
    }
    

    测试类:
    package fanshe.method;
    
    import java.lang.reflect.Method;
    
    /*
     * 获取成员方法并调用:
     * 
     * 1.批量的:
     * 		public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
     * 		public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
     * 2.获取单个的:
     * 		public Method getMethod(String name,Class<?>... parameterTypes):
     * 					参数:
     * 						name : 方法名;
     * 						Class ... : 形参的Class类型对象
     * 		public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
     * 
     * 	 调用方法:
     * 		Method --> public Object invoke(Object obj,Object... args):
     * 					参数说明:
     * 					obj : 要调用方法的对象;
     * 					args:调用方式时所传递的实参;
    
    ):
     */
    public class MethodClass {
    
    	public static void main(String[] args) throws Exception {
    		//1.获取Class对象
    		Class stuClass = Class.forName("fanshe.method.Student");
    		//2.获取所有公有方法
    		System.out.println("***************获取所有的”公有“方法*******************");
    		stuClass.getMethods();
    		Method[] methodArray = stuClass.getMethods();
    		for(Method m : methodArray){
    			System.out.println(m);
    		}
    		System.out.println("***************获取所有的方法,包括私有的*******************");
    		methodArray = stuClass.getDeclaredMethods();
    		for(Method m : methodArray){
    			System.out.println(m);
    		}
    		System.out.println("***************获取公有的show1()方法*******************");
    		Method m = stuClass.getMethod("show1", String.class);
    		System.out.println(m);
    		//实例化一个Student对象
    		Object obj = stuClass.getConstructor().newInstance();
    		m.invoke(obj, "刘德华");
    		
    		System.out.println("***************获取私有的show4()方法******************");
    		m = stuClass.getDeclaredMethod("show4", int.class);
    		System.out.println(m);
    		m.setAccessible(true);//解除私有限定
    		Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
    		System.out.println("返回值:" + result);
    		
    		
    	}
    }
    
    控制台输出:
    ***************获取所有的”公有“方法*******************
    public void fanshe.method.Student.show1(java.lang.String)
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    ***************获取所有的方法,包括私有的*******************
    public void fanshe.method.Student.show1(java.lang.String)
    private java.lang.String fanshe.method.Student.show4(int)
    protected void fanshe.method.Student.show2()
    void fanshe.method.Student.show3()
    ***************获取公有的show1()方法*******************
    public void fanshe.method.Student.show1(java.lang.String)
    调用了:公有的,String参数的show1(): s = 刘德华
    ***************获取私有的show4()方法******************
    private java.lang.String fanshe.method.Student.show4(int)
    调用了,私有的,并且有返回值的,int参数的show4(): age = 20
    返回值:abcd

    由此可见:
    m = stuClass.getDeclaredMethod("show4", int.class);//调用制定方法(所有包括私有的),需要传入两个参数,第一个是调用的方法名称,第二个是方法的形参类型,切记是类型。
    System.out.println(m);
    m.setAccessible(true);//解除私有限定
    Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
    System.out.println("返回值:" + result);
    //

    控制台输出:
    ***************获取所有的”公有“方法*******************
    public void fanshe.method.Student.show1(java.lang.String)
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    ***************获取所有的方法,包括私有的*******************
    public void fanshe.method.Student.show1(java.lang.String)
    private java.lang.String fanshe.method.Student.show4(int)
    protected void fanshe.method.Student.show2()
    void fanshe.method.Student.show3()
    ***************获取公有的show1()方法*******************
    public void fanshe.method.Student.show1(java.lang.String)
    调用了:公有的,String参数的show1(): s = 刘德华
    ***************获取私有的show4()方法******************
    private java.lang.String fanshe.method.Student.show4(int)
    调用了,私有的,并且有返回值的,int参数的show4(): age = 20
    返回值:abcd

    其实这里的成员方法:在模型中有属性一词,就是那些setter()方法和getter()方法。还有字段组成,这些内容在内省中详解

    5、反射main方法

    student类:
    package fanshe.main;
    
    public class Student {
    
    	public static void main(String[] args) {
    		System.out.println("main方法执行了。。。");
    	}
    }
    


    测试类:
    package fanshe.main;
    
    import java.lang.reflect.Method;
    
    /**
     * 获取Student类的main方法、不要与当前的main方法搞混了
     */
    public class Main {
    	
    	public static void main(String[] args) {
    		try {
    			//1、获取Student对象的字节码
    			Class clazz = Class.forName("fanshe.main.Student");
    			
    			//2、获取main方法
    			 Method methodMain = clazz.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,
    			//3、调用main方法
    			// methodMain.invoke(null, new String[]{"a","b","c"});
    			 //第一个参数,对象类型,因为方法是static静态的,所以为null可以,第二个参数是String数组,这里要注意在jdk1.4时是数组,jdk1.5之后是可变参数
    			 //这里拆的时候将  new String[]{"a","b","c"} 拆成3个对象。。。所以需要将它强转。
    			 methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
    			// methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		
    	}
    }
    

    控制台输出:
    main方法执行了。。。

    6、反射方法的其它使用之---通过反射运行配置文件内容

    student类:
    public class Student {
    	public void show(){
    		System.out.println("is show()");
    	}
    }

    配置文件以txt文件为例子(pro.txt):
    className = cn.fanshe.Student
    methodName = show

    测试类:
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    /*
     * 我们利用反射和配置文件,可以使:应用程序更新时,对源码无需进行任何修改
     * 我们只需要将新类发送给客户端,并修改配置文件即可
     */
    public class Demo {
    	public static void main(String[] args) throws Exception {
    		//通过反射获取Class对象
    		Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
    		//2获取show()方法
    		Method m = stuClass.getMethod(getValue("methodName"));//show
    		//3.调用show()方法
    		m.invoke(stuClass.getConstructor().newInstance());
    		
    	}
    	
    	//此方法接收一个key,在配置文件中获取相应的value
    	public static String getValue(String key) throws IOException{
    		Properties pro = new Properties();//获取配置文件的对象
    		FileReader in = new FileReader("pro.txt");//获取输入流
    		pro.load(in);//将流加载到配置文件对象中
    		in.close();
    		return pro.getProperty(key);//返回根据key获取的value值
    	}
    }
    

    控制台输出:
    is show()

    需求:
    当我们升级这个系统时,不要Student类,而需要新写一个Student2的类时,这时只需要更改pro.txt的文件内容就可以了。代码就一点不用改动

    要替换的student2类:
    public class Student2 {
    	public void show2(){
    		System.out.println("is show2()");
    	}
    }

    配置文件更改为:
    className = cn.fanshe.Student2
    methodName = show2
    控制台输出:
    is show2();

    7、反射方法的其它使用之---通过反射越过泛型检查

    泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的
    测试类:
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    /*
     * 通过反射越过泛型检查
     * 
     * 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?
     */
    public class Demo {
    	public static void main(String[] args) throws Exception{
    		ArrayList<String> strList = new ArrayList<>();
    		strList.add("aaa");
    		strList.add("bbb");
    		
    	//	strList.add(100);
    		//获取ArrayList的Class对象,反向的调用add()方法,添加数据
    		Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
    		//获取add()方法
    		Method m = listClass.getMethod("add", Object.class);
    		//调用add()方法
    		m.invoke(strList, 100);
    		
    		//遍历集合
    		for(Object obj : strList){
    			System.out.println(obj);
    		}
    	}
    }

    控制台输出:
    aaa
    bbb
    100

    //反射就总结到这,下面的内省章节也和反射有关,可以算是反射的高级使用吧,如果有兴趣,可以继续查看总结的内省部分。


    展开全文
  • 反射

    千次阅读 多人点赞 2019-07-14 20:30:55
    反射1.什么是反射反射的优点反射的缺点2. 类类3.一切反射相关的代码都从获得java.lang.Class类对象开始4. 反射三大作用(java.lang.reflect.*)4.1获取类对象的三种方式4.2反射实例化对象4.3 反射动态调用方法4.4 反射...

    1.什么是反射

    反射是java语言中的一种机制,通过机制可以动态的实例化对象,读写属性、调用方法

    反射的优点

    反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创和控制任何类的对象,无需提前硬编码目标类

    反射的缺点

    性能问题,使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用

    2. 类类

    所有狗 狗类 Dog 狗对象 旺财
    所有猫 猫类 Cat 猫对象 肥波
    所有类 类类 java.lang.Class 类对象 特定类

    java.lang.Class
    java.lang.reflect.Method
    java.lang.reflect.Field
    java.lang.reflect.construct
    

    (Dog.java , Cat.java…).java文件我们能不能描述成一种事物呢?
    java.lang.Class这个类就是描述Dog.java,Cat,java这些东西的
    具体的.java文件就是描述java.lang.Class这个类的一个具体的实例

    类组成部分:
    类属性 java.lang.reflect.Field (都是以java面向对象的思想对它进行封装了)
    类方法 java.lang.reflect.Method

    3.一切反射相关的代码都从获得java.lang.Class类对象开始

    3.1 Class.forName(完整类名)
    3.2 类名.class
    3.3 对象.getClass()

    4. 反射三大作用(java.lang.reflect.*)

    4.1获取类对象的三种方式

    代码演示:
    创建一个Student

    package com.myy.reflect;
    
    public class Student {
    	private String sid;
    
    	private String sname;
    
    	public Integer age;
    	
    	static{
    		System.out.println("加载进jvm中!");
    	}
    
    	public Student() {
    		super();
    		System.out.println("调用无参构造方法创建了一个学生对象");
    	}
    
    	public Student(String sid) {
    		super();
    		this.sid = sid;
    		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
    	}
    
    	public Student(String sid, String sname) {
    		super();
    		this.sid = sid;
    		this.sname = sname;
    		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
    	}
    
    	@SuppressWarnings("unused")
    	private Student(Integer age) {
    		System.out.println("调用Student类私有的构造方法创建一个学生对象");
    		this.age = age;
    	}
    
    	public String getSid() {
    		return sid;
    	}
    
    	public void setSid(String sid) {
    		this.sid = sid;
    	}
    
    	public String getSname() {
    		return sname;
    	}
    
    	public void setSname(String sname) {
    		this.sname = sname;
    	}
    
    	public void hello() {
    		System.out.println("你好!我是" + this.sname);
    	}
    
    	public void hello(String name) {
    		System.out.println(name + "你好!我是" + this.sname);
    	}
    
    	@SuppressWarnings("unused")
    	private Integer add(Integer a, Integer b) {
    		return new Integer(a.intValue() + b.intValue());
    	}
    }
    
    

    Demo1:

    package com.myy.reflect;
    
    /**
     * 获取类对象的方式
     *  通过java提供的反射机制获取到com.myy.reflect.Student.class
     *  1.Class.forName("全路径名");   jdbc/自定义mvc框架调用
     *  2.类名.class 结合泛型做通用分页查询方法会用
     *  3.类java.lang.Class(实例的类)实例(Student.class)的类实例getClass()获取  通用的增删改结合泛型使用
     *  
     * @author myy
     *
     */
    public class Demo1 {
      public static void main(String[] args) throws Exception {
    //	 1.Class.forName("全路径名");   jdbc/自定义mvc框架调用
    	Class stuClz = Class.forName("com.myy.reflect.Student");
    	System.out.println("------------");
    	
    //	 2.类名.class 结合泛型做通用分页查询方法会用
    	Class stuClz1 = Student.class;
    	System.out.println(stuClz1);
    	System.out.println("-------------");
    	
    	Student stu = new Student();
    //	3.类java.lang.Class(实例的类)实例(Student.class)的类实例getClass()获取  通用的增删改结合泛型使用
    	Class stuClz2 =  stu.getClass();
    	System.out.println(stuClz2);//并且还调用了无参构造器
    	
    	
    }
    	
    }
    

    运行结果:
    在这里插入图片描述

    4.2反射实例化对象

    代码演示:
    Demo2:

    package com.myy.reflect;
    
    /**
     * 利用反射进行对象的实例化
     *    之前:通过new关键字进行实例化
     *    现在:通过java.lang.reflect.construct来实例化对象
     *    
     * @author myy
     *
     */
    public class Demo2 {
        public static void main(String[] args) throws Exception, Exception {
    		Student stu = new Student();
    		Class stuClz = stu.getClass();
    //		newInstance这个方法默认是使用无参构造器去实例化对象
    		Student stu2 = (Student) stuClz.newInstance();
    		System.out.println(stu2);//如果不是空就意味着创建出来
    	}
    }
    

    运行结果:
    在这里插入图片描述
    提问:假设没有无参构造器运行会不会报错
    代码演示:
    首先,先把Student类的无参构造器注释掉
    在这里插入图片描述
    然后,修改一下Demo2的代码

     public static void main(String[] args) throws Exception, Exception {
    //		Student stu = new Student();
    //		Class stuClz = stu.getClass();
        	Class stuClz = Student.class;
    //		newInstance这个方法默认是使用无参构造器去实例化对象
    		Student stu2 = (Student) stuClz.newInstance();
    		System.out.println(stu2);//如果不是空就意味着创建出来
    	}
    

    如图所示运行会报错:
    在这里插入图片描述

    答:由上面代码演示我们得知当没有无参构造器的时候运行会报错。
    运行报错的原因是:没有找到匹配方法,因为它默认找的是默认无参构造器。
    注意:一定要提供无参构造器

    优势:

    1. 能够对未知的对象进行实例化
    2. 能够对私有的构造器实例化对象

    1.1代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //		调用有参构造器去实例化对象
        	Constructor<Student> constructor = stuClz.getConstructor(String.class);
        	Student stu2 = (Student)constructor.newInstance("张三");
        	
    	}
    

    运行结果:
    在这里插入图片描述
    1.2代码演示

    public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //		调用有参构造器去实例化对象(两个参数的)
        	Constructor<Student> constructor = stuClz.getConstructor(String.class,String.class);
        	Student stu2 = (Student)constructor.newInstance("t003","张三");
        	
    	}
    

    运行结果:
    在这里插入图片描述
    2.1如果按照以上的操作进行代码演示

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz.getConstructor(Integer.class);
        	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    
    

    运行结果:
    在这里插入图片描述
    getConstructor与getDeclaredConstructoe的区别
    getConstructor只能获取被public修饰的构造器
    getDeclaredConstructoe被所有关键字修饰的构造器

    所以私有的要用getDeclaredConstructoe

    如代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz. stuClz.getDeclaredConstructor(Integer.class);
        	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    

    运行结果:
    在这里插入图片描述

    Class com.myy.reflect.Demo2 can not access a member of class com.myy.reflect.Student with modifiers "private"
    

    该错误原因是:找到了私有的构造器,但不能调用因为没有权限

    则要对代码进行给予权限如代码演示:

     public static void main(String[] args) throws Exception, Exception {
        	Class stuClz = Student.class;
    //    	调用私有构造器去实例化对象
        	Constructor<Student> constructor = stuClz. stuClz.getDeclaredConstructor(Integer.class);
    constructor.setAccessible(true);//默认为false    
    	Student stu2 = (Student)constructor.newInstance(18);
        	
    	}
    

    运行结果:
    在这里插入图片描述

    4.3 反射动态调用方法

    Demo3:
    无参的代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Method;
    
    /**
     * 动态方法调用
     *  构造方法是不是方法
     * 
     * @author myy
     *
     */
    public class Demo3 {
     public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    //无参
    	Method m= stuClz.getDeclaredMethod("hello");
    	m.invoke(stu);
    }
    }
    

    运行结果:
    在这里插入图片描述
    有参的代码演示:

    public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    	//有参的
    	Method m= stuClz.getDeclaredMethod("hello", String.class);
    	m.invoke(stu, "张三");
    }
    
    

    运行结果:
    在这里插入图片描述
    私有的代码演示:

     public static void main(String[] args) throws Exception, SecurityException {
    	Student stu = new Student();
    	Class<? extends Student> stuClz = stu.getClass();//泛型里的上限定
    	//私有的
    	Method m = stuClz.getDeclaredMethod("add", Integer.class,Integer.class);
       m.setAccessible(true);
    	//	Method.invoke的返回值是被动态调用的方法的返回值
    	Object invoke = m.invoke(stu, 11,9);
    	System.out.println(invoke);
    }
    

    运行结果:
    在这里插入图片描述

    4.4 反射读写属性

    Demo4:
    代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Field;
    
    /**
     * 反射读写属性
     *  自定义标签库,通用分页,自定义mvc也要用
     * @author myy
     *
     */
    public class Demo4 {
    public static void main(String[] args) throws Exception {
    	Student stu = new Student("t003","张三");
    	stu.age = 18;
    	System.out.println(stu.getSid());
        System.out.println(stu.getSname());	
    	Class<? extends Student> stuClz = stu.getClass();
    	//私有的
    	Field f = stuClz.getDeclaredField("sname");
    	f.setAccessible(true);
    	System.out.println(f.get(stu));
    	
    //	获取当前Student实例中的stu私有属性及其属性值
    	Field[] fields = stuClz.getDeclaredFields();
    	for (Field field : fields) {
    		field.setAccessible(true);
    		System.out.println(field.getName()+":"+field.get(stu));
    	}
    }
    }
    

    运行结果:
    在这里插入图片描述

    5.访问修饰符

    如何判断类或变量、方法的修饰符,可以使用Java反射机制中,Field的 getModifiers() 方法返回int类型值表示该字段的修饰符,

    即这个方法就是返回一个int型的返回值,代表类、成员变量、方法的修饰符。

    该修饰符是java.lang.reflect.Modifier的静态属性

    对应表如下:
    PUBLIC: 1
    PRIVATE: 2
    PROTECTED: 4
    STATIC: 8
    FINAL: 16
    SYNCHRONIZED: 32
    VOLATILE: 64
    TRANSIENT: 128
    NATIVE: 256
    INTERFACE: 512
    ABSTRACT: 1024
    STRICT: 2048
    

    Modifier提供了很多静态方法,对类和成员访问修饰符进行解码。
    如代码演示:

    package com.myy.reflect;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    
    /**
     *   Modifier.isAbstract(int mod) 
     *   Modifier.isFinal(int mod) 
     *   Modifier.isInterface(int mod)
     *   Modifier.isNative(int mod)
     *   Modifier.isPrivate(int mod)
     *   Modifier.isProtected(int mod) 
     *   Modifier.isStatic(int mod)
     *   Modifier.isStrict(int mod)
     *   Modifier.isSynchronized(int mod)  
     *   Modifier.isTransient(int mod)
     *   Modifier.isVolatile(int mod) 
     *   
     * @author myy
     *
     */
    public class Demo5 {
    public static void main(String[] args) {
         Field[] fileds = Student.class.getDeclaredFields();
         for (Field field : fileds) {
    		System.out.println(field.getName()+"  访问修饰符是否包括private:"+Modifier.isPrivate(field.getModifiers()));
    	    System.out.println(field.getName()+"  访问修饰符是否包括static:"+Modifier.isStatic(field.getModifiers()));
    	    System.out.println(field.getName()+"  访问修饰符是否包括public:"+Modifier.isPublic(field.getModifiers()));
         }
    }
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • Java反射技术详解

    万次阅读 多人点赞 2019-04-14 23:11:32
    相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有...

    前言

      相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替代了,java反射有个开源框架jOOR相信很多人都用过,不过我们还是要学习反射的基础语法,这样才能自己写出优秀的框架,当然这里所讲的反射技术,是学习Android插件化技术、Hook技术等必不可少的!

    一、基本反射技术

          1.1 根据一个字符串得到一个类

            getClass方法

     String name = "Huanglinqing";
     Class c1 = name.getClass();
     System.out.println(c1.getName());
    

         打印结果如下:

        

        Class.forName

        比如我们获取java.lang.String的类名 

       String name = "java.lang.String";
       Class c1 = null;
       try {
              c1 = Class.forName(name);
              System.out.println(c1.getName());
          } catch (ClassNotFoundException e) {
      }
    

        这里也通过捕获异常,因为我们传的这个字符串可能不合法,字符串合法命名是类的命名空间和类的名称组成

        打印结果如下:

        
       我们还可以通过c1.getSuperclass()获取到他的父类

       Type属性

        基本类型都有type属性,可以得到这个基本类型的类型,比如:

    Class c1 = Boolean.TYPE;
    Class c2 = Byte.TYPE;
    Class c3 = Float.TYPE;
    Class c4 = Double.TYPE;
    
     停停停!这些东西有啥子用,如此鸡肋! 别急,一切都是为后续做准备。

    二、获取类的成员

             当类中方法定义为私有的时候我们能调用?不能!当变量是私有的时候我们能获取吗?不能!但是反射可以,比如源码中有你需要用到的方法,但是那个方法是私有的,这个时候你就可以通过反射去执行这个私有方法,并且获取私有变量。

           获取类的构造函数

           为了便于测试,我们定义一个Test类,Test类如下:(省略get和set方法)

           Test类中我们定义是三个私有变量,生成两个公有的含参构造方法和一个私有的含参构造方法以及一个公有的无参构造方法。

    public class Test {
    
        private int age;
        private String name;
        private int testint;
    
        public Test(int age) {
            this.age = age;
        }
    
        public Test(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        private Test(String name) {
            this.name = name;
        }
    
        public Test() {
        }
    

          下面我们通过反射获取这些构造方法

           获取类的所有构造方法

     Test test = new Test();
     Class c4 = test.getClass();
     Constructor[] constructors ;
     constructors = c4.getDeclaredConstructors();
    

          通过getDeclaredConstructors可以返回类的所有构造方法,返回的是一个数组因为构造方法可能不止一个,通过getModifiers可以得到构造方法的类型,getParameterTypes可以得到构造方法的所有参数,返回的是一个Class数组,所以我们如果想获取所有构造方法以及每个构造方法的参数类型,可以有如下代码:

      for (int i = 0; i < constructors.length; i++) {
            System.out.print(Modifier.toString(constructors[i].getModifiers()) + "参数:");
            Class[] parametertypes = constructors[i].getParameterTypes();
            for (int j = 0; j < parametertypes.length; j++) {
                 System.out.print(parametertypes[j].getName() + " ");
           }
          System.out.println("");
      }
    

        运行结果如下所示:

        

        这样我们就得到了类中所有构造方法和构造方法中的参数,那么我们如何获取特定的构造方法呢?

        获取类中特定的构造方法

        我们可以通过getConstructors方法获取类中 所有的public类型的构造方法,代码和上面一样就不演示了。

        我们可以通过getDeclaredConstructor()方法传参获取特定参数类型的构造方法,这里注意是getDeclaredConstructor()不是  getDeclaredConstructors() ,所以返回的是一个Class对象而不是一个Class数组。

        获取无参构造方法直接不传参数,如下所示:

       try {
              constructors = c4.getDeclaredConstructor();
              System.out.print(Modifier.toString(constructors.getModifiers()) + );
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
          }
    

        这里要进行异常捕获,因为可能不存在对应的构造方法,打印结果如下:  

        

       如果我们想获取有两个参数分别为int和String类型的构造方法,代码如下:

      Class[] p = {int.class,String.class};
      try {
           constructors = c4.getDeclaredConstructor(p);
           System.out.print(Modifier.toString(constructors.getModifiers()) + "参数:");
           Class[] parametertypes = constructors.getParameterTypes();
           for (int j = 0; j < parametertypes.length; j++) {
                System.out.print(parametertypes[j].getName() + " ");
              }
           } catch (NoSuchMethodException e) {
                e.printStackTrace();
         }
    

      这里我们同样打印出构造方法的参数:


      

      调用构造方法

       从这里开始慢慢到了关键的一步,得到类的实例,我们主要借助于newInstance方法,为了方便演示我们将测试类的两个构造方法打印出来. 

       public Test(int age, String name) {
            this.age = age;
            this.name = name;
            System.out.println("hello" + name + "i am" + age);
        }
    
    
        private Test(String name) {
            this.name = name;
            System.out.println("My Name is" +
                    name);
        }
    

       我们先来调用public的方法,如下所示:

     Class[] p = {int.class,String.class};
     constructors = c4.getDeclaredConstructor(p);
     constructors.newInstance(24,"HuangLinqing");
    

     运行打印结果如下:


      

     那么调用私有构造方法呢,和上面一样,只是我们要设置constructors.setAccessible(true);代码如下:

      Class[] p = {String.class};
      constructors = c4.getDeclaredConstructor(p);
      constructors.setAccessible(true);
      constructors.newInstance("HuangLinqing");
    

      打印结果如下:


       

    调用类的私有方法

      如何调用类中的私有方法呢,我们先在测试类中编写一个测试的私有方法 如下:

      private void welcome(String tips){
            System.out.println(tips);
        }
    

      我们知道如果我们要正常的调用类的方法都是通过类.方法调用,所以我们调用私有方法也需要得到类的实例,而我们上面newInstace已经得到了类的实例,这样就好办了。

       Class[] p4 = {String.class};
       Method method = c4.getDeclaredMethod("welcome",p4);
       method.setAccessible(true);
    

       我们首先通过 getDeclaredMethod方法获取到这个私有方法,第一个参数是方法名,第二个参数是参数类型

       然后通过invoke方法执行,invoke需要两个参数一个是类的实例,一个是方法参数。

         Class[] p4 = {String.class};
         Method method = c4.getDeclaredMethod("welcome",p4);
         method.setAccessible(true);
         Object arg1s[] = {"欢迎关注代码男人技术公众号"};
         method.invoke(test,arg1s);
    

         test类的实例当不能new 获取的时候我们也可以通过反射获取,就是上面的newInstance方法。打印结果如下:


        

     获取类的私有字段并修改值

      看到这里你可能会说,有了set方法,什么私有不私有,test.set不就可以了,但是这里要注意我们是没有办法得到这个类的实例的,要不然都可以得到实例就没有反射一说了。我们在通过反射得到类的实例之后先获取字段:

    Field field = c4.getDeclaredField("name");
    field.setAccessible(true);
    field.set(o,"代码男人");
    

       o是我们上面通过反射构造方法获取的实例,  打印field.get(o).toString()的值如下:
      

       

       不过要注意的是我们修改了name的值只对当前的实例对象有效。

     

       Java的基本反射语法就是这样了,欢迎加入技术群一起探讨!

      最后反射封装类如下:

    package jnidemo.hlq.com.hookdemo;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    /**
     * @author Huanglinqing
     * @date 2019/4/28
     */
    
    public class Reflex {
    
        /**
         * 获取无参构造函数
         * @param className
         * @return
         */
        public static Object createObject(String className) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 获取无参构造方法
         * @param clazz
         * @return
         */
        public static Object createObject(Class clazz) {
            Class[] pareTyple = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return createObject(clazz, pareTyple, pareVaules);
        }
    
        /**
         * 获取一个参数的构造函数  已知className
         *
         * @param className
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(String className, Class pareTyple, Object pareVaule) {
    
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取单个参数的构造方法 已知类
         *
         * @param clazz
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object createObject(Class clazz, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return createObject(clazz, pareTyples, pareVaules);
        }
    
        /**
         * 获取多个参数的构造方法 已知className
         * @param className
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(String className, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class r = Class.forName(className);
                return createObject(r, pareTyples, pareVaules);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取构造方法
         *
         * @param clazz
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object createObject(Class clazz, Class[] pareTyples, Object[] pareVaules) {
            try {
                Constructor ctor = clazz.getDeclaredConstructor(pareTyples);
                ctor.setAccessible(true);
                return ctor.newInstance(pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        /**
         * 获取多个参数的方法
         * @param obj
         * @param methodName
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTyples, Object[] pareVaules) {
            if (obj == null) {
                return null;
            }
    
            try {
                //调用一个private方法 //在指定类中获取指定的方法
                Method method = obj.getClass().getDeclaredMethod(methodName, pareTyples);
                method.setAccessible(true);
                return method.invoke(obj, pareVaules);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 获取一个参数的方法
         * @param obj
         * @param methodName
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = {pareTyple};
            Object[] pareVaules = {pareVaule};
    
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
    
        /**
         * 获取无参方法
         * @param obj
         * @param methodName
         * @return
         */
        public static Object invokeInstanceMethod(Object obj, String methodName) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeInstanceMethod(obj, methodName, pareTyples, pareVaules);
        }
    
    
        /**
         * 无参静态方法
         * @param className
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 获取一个参数的静态方法
         * @param className
         * @param method_name
         * @param pareTyple
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class pareTyple, Object pareVaule) {
            Class[] pareTyples = new Class[]{pareTyple};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return invokeStaticMethod(className, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 获取多个参数的静态方法
         * @param className
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(String className, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Class obj_class = Class.forName(className);
                return invokeStaticMethod(obj_class, method_name, pareTyples, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        /**
         * 无参静态方法
         * @param method_name
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name) {
            Class[] pareTyples = new Class[]{};
            Object[] pareVaules = new Object[]{};
    
            return invokeStaticMethod(clazz, method_name, pareTyples, pareVaules);
        }
    
        /**
         * 一个参数静态方法
         * @param clazz
         * @param method_name
         * @param classType
         * @param pareVaule
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class classType, Object pareVaule) {
            Class[] classTypes = new Class[]{classType};
            Object[] pareVaules = new Object[]{pareVaule};
    
            return invokeStaticMethod(clazz, method_name, classTypes, pareVaules);
        }
    
        /**
         * 多个参数的静态方法
         * @param clazz
         * @param method_name
         * @param pareTyples
         * @param pareVaules
         * @return
         */
        public static Object invokeStaticMethod(Class clazz, String method_name, Class[] pareTyples, Object[] pareVaules) {
            try {
                Method method = clazz.getDeclaredMethod(method_name, pareTyples);
                method.setAccessible(true);
                return method.invoke(null, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        public static Object getFieldObject(String className, Object obj, String filedName) {
            try {
                Class obj_class = Class.forName(className);
                return getFieldObject(obj_class, obj, filedName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static Object getFieldObject(Class clazz, Object obj, String filedName) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
    
        public static void setFieldObject(Class clazz, Object obj, String filedName, Object filedVaule) {
            try {
                Field field = clazz.getDeclaredField(filedName);
                field.setAccessible(true);
                field.set(obj, filedVaule);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void setFieldObject(String className, Object obj, String filedName, Object filedVaule) {
            try {
                Class obj_class = Class.forName(className);
                setFieldObject(obj_class, obj, filedName, filedVaule);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    
    
        public static Object getStaticFieldObject(String className, String filedName) {
            return getFieldObject(className, null, filedName);
        }
    
        public static Object getStaticFieldObject(Class clazz, String filedName) {
            return getFieldObject(clazz, null, filedName);
        }
    
        public static void setStaticFieldObject(String classname, String filedName, Object filedVaule) {
            setFieldObject(classname, null, filedName, filedVaule);
        }
    
        public static void setStaticFieldObject(Class clazz, String filedName, Object filedVaule) {
            setFieldObject(clazz, null, filedName, filedVaule);
        }
    }
    
    
     
    展开全文
  • 用最直接的大白话来聊一聊Java中的反射机制

    万次阅读 多人点赞 2019-05-26 22:44:15
    思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式 2、使用Clone的方法:无论何时...

    视频功能审核通过了,可以看视频啦!

    建议花十几分钟的时间把视频看完,然后再结合博客里的内容来理解,相信对你了解Java中的反射会有所帮助

    记得点关注啊

    用最通俗易懂的话来说一说Java中的反射机制

    思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式?

    Java中创建对象大概有这几种方式:

    1、使用new关键字:这是我们最常见的也是最简单的创建对象的方式

    2、使用Clone的方法:无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去

    3、使用反序列化:当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象

    上边是Java中常见的创建对象的三种方式,其实除了上边的三种还有另外一种方式,就是接下来我们要讨论的 “反射”

    1、反射概述

    1.1什么是反射

    反射就是把Java类中的各个部分,映射成一个个的Java对象,拿到这些对象后可以做一些事情。

    既然说反射是反射Java类中的各个组成部分,所以说咱们得知道一个类中有哪儿些部分?

    例如,一个类有:成员变量,方法,构造方法,等信息,利用反射技术咱们可以把这些组成部分映射成一个个对象。

    1.2、反射能干什么

    说完反射的概念后,咱们说一下反射能干什么?

    一般来说反射是用来做框架的,或者说可以做一些抽象度比较高的底层代码,反射在日常的开发中用到的不多,但是咱们还必须搞懂它,因为搞懂了反射以后,可以帮助咱们理解框架的一些原理。所以说有一句很经典的话:反射是框架设计的灵魂。现在说完这个可能还不太能理解,不急,等下说完一个快速入门的例子后,应该会稍微有点感觉

    1.3、怎么得到想反射的类

    刚才已经说过,反射是对一个类进行解剖,想解剖一个东西,前提是首先你得拿到这个东西,那么怎么得到咱们想解剖的类呢?

    首先大家要明白一点,咱们写的代码是存储在后缀名是 .java的文件里的,但是它会被编译,最终真正去执行的是编译后的 .class文件。Java是面向对象的语言,一切皆对象,所以java认为 这些编译后的 class文件,这种事物也是一种对象,它也给抽象成了一种类,这个类就是Class,大家可以去AIP里看一下这个类

    所以拿到这个类后,就相当于拿到了咱们想解剖的类,那怎么拿到这个类?

    看API文档后,有一个方法forName(String className); 而且是一个静态的方法,这样咱们就可以得到想反射的类了

    到这里,看Class clazz = Class.forName("com.cj.test.Person");这个应该有点感觉了吧

    Class.forName("com.cj.test.Person");因为这个方法里接收的是个字符串,字符串的话,我们就可以写在配置文件里,然后利用反射生成我们需要的对象,这才是我们想要的。很多框架里都有类似的配置

    2、解剖类

    我们知道一个类里一般有构造函数、方法、成员变量(字段/属性)这三部分组成

    翻阅API文档,可以看到

    Class对象提供了如下常用方法:

    public Constructor getConstructor(Class<?>…parameterTypes)

    public Method getMethod(String name,Class<?>… parameterTypes)

    public Field getField(String name)

    public Constructor getDeclaredConstructor(Class<?>…parameterTypes)

    public Method getDeclaredMethod(String name,Class<?>… parameterTypes)

    public Field getDeclaredField(String name)

    这些方法分别用于帮咱们从类中解剖出构造函数、方法和成员变量(属性)。

    然后把解剖出来的部分,分别用Constructor、Method、Field对象表示。

    2.1反射构造方法

    2.1.1反射无参的构造函数

    可以看到 默认的无参构造方法执行了

    从上边的例子看出,要想反射,首先第一步就是得到类的字节码

    所以简单说一下得到类的字节码的几种方式

    (1)、Class.forName("com.cj.test.Person"); 这就是上边我们用的方式

    (2)、对象.getClass();

    (3)、类名.class;

    2.1.2反射“一个参数”的构造函数

    2.1.3反射“多个参数”的构造函数

    2.1.4反射“私有”的构造函数

    注意:在反射私有的构造函数时,用普通的clazz.getConstructor()会报错,因为它是私有的,所以提供了专门反射私有构造函数的方法 clazz.getDeclaredConstructor(int.class);//读取私有的构造函数,用这个方法读取完还需要设置一下暴力反射才可以

    c.setAccessible(true);//暴力反射

    2.1.5反射得到类中所有的构造函数

     

    2.2反射类中的方法

    package com.cj.test;
    
    import java.util.Date;
    
    public class Person {
    	
    	public Person(){
    		System.out.println("默认的无参构造方法执行了");
    	}
    
    	public Person(String name){
    		System.out.println("姓名:"+name);
    	}
    	
    	public Person(String name,int age){
    		System.out.println(name+"="+age);
    	}
    	
    	private Person(int age){
    		System.out.println("年龄:"+age);
    	}
    	
    	public void m1() {
    		System.out.println("m1");
    	}
    	
    	public void m2(String name) {
    		System.out.println(name);
    	}
    	
    	public String m3(String name,int age) {
    		System.out.println(name+":"+age);
    		return "aaa";
    	}
    	
    	private void m4(Date d) {
    		System.out.println(d);
    	}
    	
    	public static void m5() {
    		System.out.println("m5");
    	}
    	
    	public static void m6(String[] strs) {
    		System.out.println(strs.length);
    	}
    
            public static void main(String[] args) {
    		System.out.println("main");
    	}
    
    }
    
    
    
    
    
    package com.cj.test;
    
    import java.lang.reflect.Method;
    import java.util.Date;
    import org.junit.Test;
    
    public class Demo2 {
    
    	@Test//public void m1()
    	public void test1() throws Exception{
    		Class clazz = Class.forName("com.cj.test.Person");
    		Person p = (Person)clazz.newInstance();
    		Method m = clazz.getMethod("m1", null);
    		m.invoke(p, null);
    	}
    	@Test//public void m2(String name)
    	public void test2() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getMethod("m2", String.class);
    		m.invoke(p, "张三");
    	}
    	@Test//public String m3(String name,int age)
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getMethod("m3", String.class,int.class);
    		String returnValue = (String)m.invoke(p, "张三",23);
    		System.out.println(returnValue);
    	}
    	@Test//private void m4(Date d)
    	public void test4() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person) clazz.newInstance();
    		Method m = clazz.getDeclaredMethod("m4", Date.class);
    		m.setAccessible(true);
    		m.invoke(p,new Date());
    	}
    	@Test//public static void m5()
    	public void test5() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getMethod("m5", null);
    		m.invoke(null,null);
    	}
    	@Test//private static void m6(String[] strs)
    	public void test6() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getDeclaredMethod("m6",String[].class);
    		m.setAccessible(true);
    		m.invoke(null,(Object)new String[]{"a","b"});
    	}
    	@Test
    	public void test7() throws Exception{
    		Class clazz = Person.class;
    		Method m = clazz.getMethod("main",String[].class);
    		m.invoke(null,new Object[]{new String[]{"a","b"}});
    	}
    }
    

    *****注意:看下上边代码里test6和test7的invoke方法里传的参数和其他的有点不一样

    这是因为 jdk1.4和jdk1.5处理invoke方法有区别

    1.5:public Object invoke(Object obj,Object…args)

    1.4:public Object invoke(Object obj,Object[] args)

    由于JDK1.4和1.5对invoke方法的处理有区别, 所以在反射类似于main(String[] args) 这种参数是数组的方法时需要特殊处理

    启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数个数不对的问题。

    上述问题的解决方法:

    (1)mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});

    这种方式,由于你传的是一个数组的参数,所以为了向下兼容1.4的语法,javac遇到数组会给你拆开成多个参数,但是由于咱们这个Object[ ] 数组里只有一个元素值,所以就算它拆也没关系

    (2)mainMethod.invoke(null,(Object)new String[]{"xxx"});

    这种方式相当于你传的参数是一个对象,而不是数组,所以就算是按照1.4的语法它也不会拆,所以问题搞定

    编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了

    对上边的描述进行一下总结:在反射方法时,如果方法的参数是一个数组,考虑到向下兼容问题,会按照JDK1.4的语法来对待(JVM会把传递的数组参数拆开,拆开就会报参数的个数不匹配的错误)
    解决办法:防止JVM拆开你的数组
        方式一:把数组看做是一个Object对象
        方式二:重新构建一个Object数组,那个参数数组作为唯一的元素存在。

    2.3反射类中的属性字段

    package com.cj.test;
    
    import java.util.Date;
    
    public class Person {
    	
    	public String name="李四";
    	private int age = 18;
    	public static Date time;
    	
    	public int getAge() {
    		return age;
    	}
    	
    	public Person(){
    		System.out.println("默认的无参构造方法执行了");
    	}
    
    	public Person(String name){
    		System.out.println("姓名:"+name);
    	}
    	
    	public Person(String name,int age){
    		System.out.println(name+"="+age);
    	}
    	
    	private Person(int age){
    		System.out.println("年龄:"+age);
    	}
    	
    	public void m1() {
    		System.out.println("m1");
    	}
    	
    	public void m2(String name) {
    		System.out.println(name);
    	}
    	
    	public String m3(String name,int age) {
    		System.out.println(name+":"+age);
    		return "aaa";
    	}
    	
    	private void m4(Date d) {
    		System.out.println(d);
    	}
    	
    	public static void m5() {
    		System.out.println("m5");
    	}
    	
    	public static void m6(String[] strs) {
    		System.out.println(strs.length);
    	}
    	
    	public static void main(String[] args) {
    		System.out.println("main");
    	}
    	
    }
    
    
    
    
    
    package com.cj.test;
    
    import java.lang.reflect.Field;
    import java.util.Date;
    import org.junit.Test;
    
    public class Demo3 {
    	//public String name="李四";
    	@Test
    	public void test1() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person)clazz.newInstance();
    		Field f = clazz.getField("name");
    		String s = (String)f.get(p);
    		System.out.println(s);
    		
    		//更改name的值
    		f.set(p, "王六");
    		System.out.println(p.name);
    	}
    	@Test//private int age = 18;
    	public void test2() throws Exception{
    		Class clazz = Person.class;
    		Person p = (Person)clazz.newInstance();
    		Field f = clazz.getDeclaredField("age");
    		f.setAccessible(true);
    		int age = (Integer)f.get(p);
    		System.out.println(age);
    		
    		f.set(p, 28);
    		age = (Integer)f.get(p);
    		System.out.println(age);
    	}
    	@Test//public static Date time;
    	public void test3() throws Exception{
    		Class clazz = Person.class;
    		Field f = clazz.getField("time");
    		f.set(null, new Date());
    		System.out.println(Person.time);
    	}
    }
    

    以上就是自己对Java中反射的一些学习总结,欢迎大家留言一起学习、讨论

    看完上边有关反射的东西, 对常用框架里的配置文件是不是有点思路了

    上边是Spring配置文件里的常见的bean配置,这看起来是不是可以用反射很轻易的就可以实现:解析xml然后把xml里的内容作为参数,利用反射创建对象。

    拓展:

    1、除了上述的Spring配置文件里会用到反射生成bean对象,其他常见的MVC框架,比如Struts2、SpringMVC等等一些框架里还有很多地方都会用到反射。

    前端夜页面录入的一些信息通过表单或者其他形式传入后端,后端框架就可以利用反射生成对应的对象,并利用反射操作它的set、get方法把前端传来的信息封装到对象里。

    感兴趣的话可以看下这篇:利用Java反射模拟一个Struts2框架 Struts2主要核心设计 手动实现Struts2核心代码,这篇里边包含了XML解析、反射的东西,模拟了一个Struts2的核心代码

    2、框架的代码里经常需要利用反射来操作对象的set、get方法,来把程序的数据封装到Java对象中去。

    如果每次都使用反射来操作对象的set、get方法进行设置值和取值的话,过于麻烦,所以JDK里提供了一套API,专门用于操作Java对象的属性(set/get方法),这就是内省

    关于内省相关的内容我也整理了一篇文章,感兴趣可以点击:Java反射——内省(Introspector)以及BeanUtils内省框架

    3、平常用到的框架,除了配置文件的形式,现在很多都使用了注解的形式。

    其实注解也和反射息息相关:使用反射也能轻而易举的拿到类、字段、方法上的注解,然后编写注解解析器对这些注解进行解析,做一些相关的处理

    所以说不管是配置文件还是注解的形式,它们都和反射有关。注解和自定义注解的内容,最近也抽时间大概整理了一下,感兴趣的小可爱可以点击了解:Java中的注解以及自定义注解

    写在最后:反射是框架的灵魂,具备反射知识和思想,是看懂框架的基础。希望看完文章后对你能有所帮助。

    亲们,可以点关注,点赞,3Q~

    展开全文
  • Java基础篇:反射机制详解

    万次阅读 多人点赞 2018-09-29 10:19:50
    一、什么是反射反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,并且对于任意一个类,都能够知道这个类的所有属性和方法,调用方法/访问属性,不需要提前在编译期...
  • 什么是反射反射有什么用处? 1. 什么是反射? “反射(Reflection)能够让运行于JVM中的程序检测和修改运行时的行为。”这个概念常常会和内省(Introspection)混淆,以下是这两个术语在Wikipedia中的解释: ...
  • 【1】反射机制

    万次阅读 2019-11-26 22:28:19
    知识点1:什么是Java反射 知识点2:反射机制的作用 知识点3:反射机制获取类有三种方法 知识点4:反射创建对象的方式 知识点5:反射创建api 知识点6:使用反射为类私有属性赋值 知识点7:JDBC反射加载驱动 ...
  • JAVA中的反射机制

    万次阅读 多人点赞 2014-01-08 22:31:58
    反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧!  一,先看一下反射的概念:   主要是指程序可以访问,检测和...
  • Java反射

    万次阅读 多人点赞 2019-08-28 22:58:42
    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。 用途 ...
  • jvm执行反射

    万次阅读 2018-11-29 14:54:40
    反射是java中一个相当重要的特性,它的应用十分广泛。譬如java调试器,在调试过程中枚举对象所有字段的值。在Web开发中,各种可配置的框架。为了框架的扩展性,基本上都是使用反射机制。譬如Spring的IOC容器。当然,...
  • 什么是反射

    万次阅读 多人点赞 2019-06-14 10:51:37
    什么是反射? Java 反射,就是在运行状态中。 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等 获取任意对象的属性,并且能改变对象的属性 调用任意对象的方法 判断任意一个对象所属...
  • Java反射有多强? 他拥有这五大神奇功能!

    万次阅读 多人点赞 2020-10-24 08:06:12
    Java反射是什么?Java反射有什么用?Java反射究竟有多方便?让我们一起见证反射的伟大吧!
  • java利用反射实现文件的读取

    万次阅读 2020-10-11 00:06:56
    java反射 java从很早的版本开始就引入了反射机制,java如今的框架底层大部分也都是使用反射实现的。 这篇博客就去探索下java反射使用的方便之处。 要说java的反射机制,肯定离不开Class这个类,我们从jdk的源码可以...
  • 面试官:反射都不会,还敢说自己会Java?

    万次阅读 多人点赞 2020-04-29 15:50:03
    一、反射机制 1.1 框架   在学习Java的路上,相信你一定使用过各种各样的框架。所谓的框架就是一个半成品软件,已经对基础的代码进行了封装并提供相应的API。在框架的基础上进行软件开发,可以简化编码。学习使用...
  • Java笔试面试-反射和动态代理

    万次阅读 多人点赞 2019-09-19 09:28:41
    反射   反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect)的能力。简单来说就是通过反射,可以在运行期间获取、检测和调用对象的属性和方法。 反射的使用场景 1.编程工具 IDEA 或 ...
  • Java核心:第一章:Java反射

    万次阅读 多人点赞 2020-05-11 11:04:34
    首先学习反射之前,我要提出疑问: 反射是个什么东西?它是用来做什么的?为啥要用它?它有什么优缺点?它的工作原理是什么?平时的应用场景有哪些?我怎么使用它?(何时用,怎么用,为啥要用等等) 这么多的问题...
  • 反射详解

    万次阅读 2020-05-11 19:42:21
    反射 什么是反射: Class类 获得class类对象的三种方式 Student.class 类名.class Student stu = new Student(); stu.getClass(); 对象.getClass(); Class.forName(“com.qcby.entity.Student”); 字符串是一...
  • 细说反射,Java 和 Android 开发者必须跨越的坎

    万次阅读 多人点赞 2017-07-06 23:36:13
    但是,我已经写了注解和动态代理这两个知识点的博客,阅读量还可以,这两个知识点是属于反射机制中的,现在对于注解和动态代理息息相关的反射知识基础我倒是退缩了,所以说看起来很普通的东西,其实真的要一五一十地...
  • 反射机制及反射原理

    万次阅读 2018-04-25 19:32:36
    反射机制:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的...
  • 反射性能问题 禁止安全检查,可以提高反射的运行速度: 使用普通方法调用、使用反射增加安全检查、使用反射不进行安全检查的运行效率对比,结果如下: 反射操作泛型 编译器编译的时候有泛型,经过编译,...
  • 是啊,在阐述某个观点时确实有必要说明原因,并且证明这个观点是对的,虽然反射影响性能人尽皆知,我曾经也真的研究过反射是否存在性能问题,但并没有在写文章的时候详细说明。这让我想到网上很多信息只会告诉你结论...
  • python反射

    千次阅读 2020-02-02 01:28:48
    反射是一个很重要的概念,它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。 python中把反射直接写成类的默认方法实现机制和java等有所差别,其实属于一种伪反射 直接上代码 class ...
  • Java反射机制

    万次阅读 热门讨论 2018-06-25 14:54:06
    Spring Ioc的原理是工厂+反射,所谓IOC即是控制反转,控制反转是一种思想,一个类想要完成一个功能,非常常见的是需要和其他对象进行合作完成,例如,分层系统中,service层调用dao层,则需要在service层new出一个dao层对象,...
  • 【java反射反射是啥?是干啥用的?

    万次阅读 多人点赞 2019-01-04 21:45:24
    反射是啥 反射既然有“反”,就说明它是一个逆向的过程。那我们先来看看正向过程是怎样的。 设计一个类,类实例化成对象,对象调方法或属性去实现一些功能。 那反射是什么呢? 不知道大家是否还记得上图,这是刚...
  • 一个例子让你了解Java反射机制

    万次阅读 多人点赞 2013-10-18 21:53:13
    JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们...
  • 反射都不懂,框架你怎么能学懂啊

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 151,161
精华内容 60,464
关键字:

反射