java中什么是反射_java中反射是什么?什么情况下用反射 - CSDN
精华内容
参与话题
  • java中 什么是反射

    2020-04-23 16:00:21
    java 什么是反射? JAVA反射机制是在运行状态,对于任意一个实体类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法...

    java中 什么是反射?

     

    JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;

    对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

    JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

     

    获取String的方法

    public class DumpMethods {
    
    
        public static void main(String[] args) throws Exception{
            
            Class<?> classType = Class.forName("java.lang.String");
    
            Method[] methods =classType.getDeclaredMethods();
    
            for (Method method:methods){
                System.out.println(method);
            }
    
        }
    
    
    }

     

    截图:

     

     

     

     

     

    通过反射调用方法 
      通过反射调用方法。详情见代码及注释:
    import java.lang.reflect.Method;
    public class InvokeTester
    {
        public int add(int param1, int param2)
        {
            return param1 + param2;
        }
        public String echo(String message)
        {
            return "Hello: " + message;
        }
        public static void main(String[] args) throws Exception
        {
            // 以前的常规执行手段
            InvokeTester tester = new InvokeTester();
            System.out.println(tester.add(1, 2));
            System.out.println(tester.echo("Tom"));
            System.out.println("---------------------------");
    
            // 通过反射的方式
            // 第一步,获取Class对象
            // 前面用的方法是:Class.forName()方法获取
            // 这里用第二种方法,类名.class
            Class<?> classType = InvokeTester.class;
    
            // 生成新的对象:用newInstance()方法
            Object invokeTester = classType.newInstance();
            System.out.println(invokeTester instanceof InvokeTester); // 输出true
    
    
    
            // 通过反射调用方法
            // 首先需要获得与该方法对应的Method对象
            Method addMethod = classType.getMethod("add", new Class[] { int.class,  int.class });
    
            // 第一个参数是方法名,第二个参数是这个方法所需要的参数的Class对象的数组
            // 调用目标方法
            Object result = addMethod.invoke(invokeTester, new Object[] { 1, 2 });
            System.out.println(result); // 此时result是Integer类型
    
            //调用第二个方法
            Method echoMethod = classType.getDeclaredMethod("echo", new Class[]{String.class});
            Object result2 = echoMethod.invoke(invokeTester, new Object[]{"Tom"});
            System.out.println(result2);
        }
    }

     

     

     
     
     
     
     
     
     
    posted @ 2019-03-13 09:52 梓鸿 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • 用最直接的大白话来聊一聊Java中反射机制

    万次阅读 多人点赞 2020-08-24 09:41:28
    思考:在讲反射之前,先思考一个问题,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里的内容作为参数,利用反射创建对象。

    除了这个,常用的框架里还有很多地方都用到了反射,反射是框架的灵魂,具备反射知识和思想,是看懂框架的基础

    平常用到的框架,除了配置文件的形式,现在很多都使用了注解的形式,其实注解也和反射息息相关,使用反射也能轻而易举的拿到类、字段、方法上的注解,然后编写注解解析器对这些注解进行解析,做一些相关的处理,所以说不管是配置文件还是注解的形式,它们都和反射有关

    感兴趣的话可以看下这篇,这篇里边包含了XML解析、反射的东西,模拟了一个Struts2的核心代码

    利用Java反射模拟一个Struts2框架 Struts2主要核心设计 手动实现Struts2核心代码

    跟反射相关的还有内省、自定义注解,最近也抽时间大概整理了一下

    Java反射——内省(Introspector)以及BeanUtils内省框架

    Java中的注解以及自定义注解

    感兴趣的小可爱可以了解一下~

    觉得对你有帮助的话,可以点个关注,点个赞,3Q~

     

    展开全文
  • JAVA中反射什么

    2018-12-06 17:31:32
    能够分析能力的程序成为反射,通俗的来讲就是能够通过运行时的类名获取类的全部信息。反射机制可以用来干以下的事情: 1、在运行时分析类的能力 2、在运行时查看对象,例如,编写一个toString()方法供所有类使用 ...

    能够分析能力的程序成为反射,通俗的来讲就是能够通过运行时的类名获取类的全部信息。反射机制可以用来干以下的事情:

    1、在运行时分析类的能力

    2、在运行时查看对象,例如,编写一个toString()方法供所有类使用

    3、实现通用的数组操作代码

    4、利用Method对象,这个对象很像C++中的函数指针

    下面来说一说他的底层实现原理:

    在程序运行期间,JVM始终对所有的对象都有跟踪,并且将其所有信息存入一个类型为Class的对象中,选择对应的方法进行执行,即在程序运行时自动分析需要使用的类,并且通过newInstance()的方法动态的加载类。

    反射的应用:

    先看一下如下例子:

    在没有使用反射时,每次增加一个水果都需要修改Factory中的代码,这样会很麻烦的

    interface fruit{  
        public abstract void eat();  
    }  
        
    class Apple implements fruit{  
        public void eat(){  
            System.out.println("Apple");  
        }  
    }  
        
    class Orange implements fruit{  
        public void eat(){  
            System.out.println("Orange");  
        }  
    }  
        
    // 构造工厂类  
    // 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了  
    class Factory{  
        public static fruit getInstance(String fruitName){  
            fruit f=null;  
            if("Apple".equals(fruitName)){  
                f=new Apple();  
            }  
            if("Orange".equals(fruitName)){  
                f=new Orange();  
            }  
            return f;  
        }  
    }  
    class hello{  
        public static void main(String[] a){  
            fruit f=Factory.getInstance("Orange");  
            f.eat();  
        }  
        
    }  

    使用反射:

    interface fruit{  
        public abstract void eat();  
    }  
       
    class Apple implements fruit{  
        public void eat(){  
            System.out.println("Apple");  
        }  
    }  
       
    class Orange implements fruit{  
        public void eat(){  
            System.out.println("Orange");  
        }  
    }  
       
    class Factory{  
        public static fruit getInstance(String ClassName){  
            fruit f=null;  
            try{  
                f=(fruit)Class.forName(ClassName).newInstance();  //forName使用反射获取类,newInstance获取实例
            }catch (Exception e) {  
                e.printStackTrace();  
            }  
            return f;  
        }  
    }  
    class hello{  
        public static void main(String[] a){  
            fruit f=Factory.getInstance("Reflect.Apple");  
            if(f!=null){  
                f.eat();  
            }  
        }  
    }

     这样一来,我们就不用在每一次增加水果种类时修改Factory类,由此可以看到反射的好处,那么问题来了,为什么不在任何地方都使用反射呢,这是因为,反射虽然节省了操作,但是他所占用的资源开销是很大的,因此我们要根据实际情况使用反射。

    下面来说一下反射的具体使用方法:

    java.lang.reflect包中有三个类Filed、Method、Constructor分别用于描述类的域、方法、构造器。这三个类都有一个getName()的方法,用来返回项目的名称。此外三个类中都有一个getModifiers()方法,用来分析访问修饰符使用情况。

    获得构造函数的方法 
        Constructor getConstructor(Class[] params)//根据指定参数获得public构造器

        Constructor[] getConstructors()//获得public的所有构造器

        Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器

        Constructor[] getDeclaredConstructors()//获得public的所有构造器 

    获得类方法的方法 
        Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法

        Method[] getMethods()//获得所有的public方法

        Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法

        Method[] getDeclaredMethods()//获得所以的public和非public方法 

    获得类中属性的方法 
        Field getField(String name)//根据变量名得到相应的public变量

        Field[] getFields()//获得类中所以public的方法

        Field getDeclaredField(String name)//根据方法名获得public和非public变量

        Field[] getDeclaredFields()//获得类中所有的public和非public方法

    示例如下:

    package test;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.Scanner;
    
    public class Tresgt {
    	
    		public static void main(String args[]) {
    			String name = "test.test121";
    //			if(args.length>0)name=args[0];
    //			else {
    //				Scanner in =new Scanner(System.in);
    //				System.out.println("Enter class name (e.g.java.until.Date):");
    //				name=in.next();
    //			}
    			try {
    				Class c1=Class.forName(name);
    				Class superc1=c1.getSuperclass();
    				System.out.println("----------------------"+c1.getModifiers());
    				String modifiers=Modifier.toString(c1.getModifiers());
    				if(modifiers.length()>0)
    					System.out.println(modifiers+"");
    				System.out.println("class:"+name);
    				if(superc1!=null&&superc1!=Object.class)
    					System.out.println("extends"+superc1.getName());
    				System.out.println("\n{\n");
    				System.out.println("------------------------------------");
    				printConstructors(c1);
    				System.out.println();
    				System.out.println("------------------------------------");
    				printMethods(c1);
    				System.out.println();
    				System.out.println("------------------------------------");
    				printFields(c1);
    				System.out.println("}");
    			}
    			catch(ClassNotFoundException e) {
    				e.printStackTrace();
    			}
    			System.exit(0);
    		}
    
    	public static void printConstructors(Class c1){
    		Constructor[] contructors = c1.getConstructors();
    		for(Constructor c : contructors){
    			String name = c.getName();
    			System.out.print(" ");
    			String m = Modifier.toString(c.getModifiers());
    			if(m.length() > 0)
    				System.out.print(m+" ");
    			System.out.print(name + "(");
    			Class[] p = c.getParameterTypes();
    			for(int j = 0 ; j < p.length;j++){
    				if(j> 0)
    					System.out.print(", ");
    				System.out.print(p[j].getName());
    			}
    			System.out.println(");");
    		}
    		
    	}
    	
    	
    	
    	public static void printFields(Class c1) {
    		Field[] fields = c1.getFields();
    		
    		for(Field f:fields) {
    			Class type =f.getType();
    			String name= f.getName();
    			System.out.print("");
    			String modifiers=Modifier.toString(f.getModifiers());
    			if(modifiers.length()>0)
    				System.out.print(modifiers+"");
    			System.out.println(type.getName()+""+name+";");
    			
    		}
    	}
    	
    	
    	
    	
    	public static void printMethods(Class cl)
    	{
    		Method[] methods = cl.getMethods();
    		for(Method m : methods)
    		{
    			Class retType = m.getReturnType();
    			String name = m.getName();
    			System.out.println(" ==========--------  ");
    			String modifiers = Modifier.toString(m.getModifiers());
    			if(modifiers.length() > 0)
    			{
    				System.out.println(modifiers+"");
    			}
    			System.out.print(retType.getName()+" "+name+"(");
    			Class[] paramTypes=m.getParameterTypes();
    			for(int j=0;j<paramTypes.length;j++)
    			{
    				if(j>0)
    				{
    					System.out.println(",");
    				}
    				System.out.println(paramTypes[j].getName());
    			}
    			System.out.println(");");
    		}
    	}
    
    }
    

    结果:

    展开全文
  • java反射】反射是啥?是干啥用的?

    万次阅读 多人点赞 2019-01-17 17:16:37
    反射什么呢? 不知道大家是否还记得上图,这是刚接触java时学到的知识。我自己的理解是现在是知道1,反推到2,然后再通过2得到一些别的信息。(这只是我的推测,至于具体是不是,还需日后深究) 类比到现实的...
    反射是啥?

    反射既然有“反”,就说明它是一个逆向的过程。那我们先来看看正向过程是怎样的。
    设计一个类,类实例化成对象,对象调方法或属性去实现一些功能。
    在这里插入图片描述
    那反射是什么呢?

    不知道大家是否还记得上图,这是刚接触java时学到的知识。我自己的理解是现在是知道1,反推到2,然后再通过2得到一些别的信息。(这只是我的推测,至于具体是不是,还需日后深究)
    类比到现实中的场景是:

    你:妈妈,你知道剪刀在哪吗?
    妈妈:我那天放针线的时候好像在针线盒里看到了,你去找找有没有。针线盒在客厅的茶几上。
    你:好的。
    

    然后你从“针线”推导出了“针线盒”,再从“针线盒”中找到了“剪刀”。
    在这里插入图片描述
    我们的反射就是:从类或对象中推导出Class类,然后再从Class类中获得类的信息。
    更迷糊了?不急,请往下看。

    找到针线盒——获取Class类

    先开始说Class类是什么?

    Class类就是People类的类,就像People类是p的类一样。Class类是p的“爷爷”。
    在这里插入图片描述
    我们可以这样理解:java.lang.Class的实例对象是People,People的实例对象是p。我们的思路就是通过People类或p对象获得Class类,然后再通过Class类获取People类的信息,比如属性,方法,构造函数等等。

    知道了Class类是什么,那我们说说怎么才能获取它。

    找到Class类有3种方法:
    在这里插入图片描述
    值得一提的是,c1、c2、c3叫做People类的“类类型”。好了,现在我们总结一下已知条件:
    People:类
    p:对象
    c:类类型

    找到剪刀——获取People类的信息

    应用一:获取类的全部方法

    在这里插入图片描述
    在获取People类的方法中,ms是一个存放着People类方法的数组,通过循环,一层层获取它的名称、参数类型、返回值。
    最后直接在main函数中调用即可
    在这里插入图片描述
    得到的部分结果如下:
    在这里插入图片描述

    应用二:获取类的全部属性

    在这里插入图片描述
    调用和调用方法类似:
    在这里插入图片描述
    运行结果:
    在这里插入图片描述

    应用三:获取类的构造函数

    构造函数类似,不再赘述。
    在这里插入图片描述

    应用四:获取类的某个特定方法

    在这里插入图片描述
    运行结果如下,两种调用方式结果相同:
    在这里插入图片描述
    以上只是对个别功能的列举,更具体的可以去API文档中寻找:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
    在这里插入图片描述

    反射的概念

    在文章的最后,我们总结一下反射的概念,让思想升华一下。

    反射的定义是什么?

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,这种动态获取、调用对象方法的功能称为java语言的反射机制。

    反射存在的必要性?

    “反射机制是很多java框架的基石”。
    (1)在xml文件或者properties里面写好了配置,然后在Java类里面解析xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护起来就很方便了。
    (2)有时候要适应某些需求,Java类里面不一定能直接调用另外的方法,这时候也可以通过反射机制来实现。

    反射的缺点?

    我们在代码中也能看到,反射的代码比正常调用的代码更多,性能也慢,所以应避免使用反射。这就相当于如果你本来就知道剪刀在哪,就没必要再通过针线——针线盒——剪刀这条路了。

    是否使用反射的标准是啥?

    如果一个功能可以不用反射完成,那么最好就不用。

    小结
    动态代理、spring中的AOP等都用了反射的思想。至于具体怎么用的,请期待接下来的博客。
    展开全文
  • java中什么是反射

    2019-05-13 17:27:44
    浅层次理解:言简意赅的说:反射就是把类的方法和属性当做对象来使用(对象就可以调用方法了,比如spring那里的invoke) 深入了解,转大佬的,点这里! ...
  • Java基础之—反射(非常重要)

    万次阅读 多人点赞 2017-05-17 09:49:02
    JAVA反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。...
  • 什么是反射?什么Java反射

    万次阅读 2018-06-11 22:16:31
    什么是反射(Reflection )?主要是指程序可以访问、检测和修改它本身状态或行为的一种能力Java反射?在Java运行时环境,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一...
  • Java 反射调用静态方法

    万次阅读 2020-01-20 08:46:27
    Java 反射调用静态方法 参考地址:Java 反射调用静态方法
  • java反射作用与意义

    万次阅读 2018-08-23 13:38:08
    2、反射的作用:通过反射可以使程序代码访问装载到JVM 的类的内部信息 获取已装载类的成员变量信息 获取已装载类的方法 获取已装载类的构造方法信息     常用方法: getName()获得类的完整名字 get...
  • java反射无所不能,辣么,怎么通过反射设置一个属性的值呢? 主程序:/** * @author tengqingya * @create 2017-03-05 15:54 */ public class TestReflectSet { private String readOnly; public String ...
  • Java反射的作用用途

    千次阅读 多人点赞 2019-02-26 17:16:45
    反射最重要的用途就是开发各种通用框架,比如在spring,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器获取Bean来依赖注入时,容器会读取配置,而配置给的就是类的信息...
  • java反射原理-重要

    万次阅读 多人点赞 2018-11-21 11:23:54
    1,JAVA反射机制是在运行状态 对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的...
  • java面试题--java反射机制

    万次阅读 2015-04-10 15:04:50
    Java反射机制的作用: 1)在运行时判断任意一个对象所属的类。 2)在运行时判断任意一个类所具有的成员变量和方法。 3)在运行时任意调用一个对象的方法 4)在运行时构造任意一个类的对象 拓展: 1、什么...
  • java映射和反射的理解

    千次阅读 2019-05-21 19:25:15
    反射是在运行状态任何一个类,我们都能知道这个类的属性和方法,对于任何一个对象都能调用这个对象的任意属性和方法,这种动态的获取信息或者动态调用对象的方法称为Java反射机制。 那么反射能做什么 1.运行时...
  • Java反射常见面试题

    万次阅读 2019-09-29 13:41:12
    1. 什么是反射反射是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言...
  • Java通过反射机制调用某个类的方法

    万次阅读 2018-06-02 10:53:24
    通过反射机制调用类的方法,主要用到下面的方法: public Object invoke(Object obj, Object... args) 参数: obj是调用基础方法的实例对象 调用基础方法索要传递的参数,参数是一个变长类型 下面是一个具体...
  • java通过反射获取List的泛型

    万次阅读 2014-04-21 11:29:46
    Field[] fields = bean.getClass().getDeclaredFields(); for(Field f : fields){ ... if(f.getType() == java.util.List.class){ // 如果是List类型,得到其Generic的类型 Type
  • Java 反射和映射(主要描述下反射)

    万次阅读 2020-07-20 11:25:29
    什么是反射?等同于映射吗? 完全不相关的。反射是一个机机制,映射是一种关系。 反射机制是在运行状态,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和...
  • Java——通过反射获取函数参数名称

    万次阅读 2017-04-30 22:55:16
    通过javassit获取参见 http://blog.csdn.net/viviju1989/article/details/8529453 这篇文章的方法一,实现比较麻烦,就不说了。通过spring的LocalVariableTableParameterNameDiscovererpublic static List<String> ...
  • 问题:在用反射时出现错误java.lang.NoSuchMethodException 原因:反射调用的方法参数列表包含int、boolean等类型,使用反射时将这些参数对应的类写成了Integer.class、Boolean.class 解决:这些参数对应的类...
1 2 3 4 5 ... 20
收藏数 290,840
精华内容 116,336
关键字:

java中什么是反射