热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java反射快速入门(一)

本文会从以下几个方面讲起①反射的简单解释②java反射的API接口及demo③反射的优缺点、应用场景一、什么是反射?java反射:在程序运行中动态获取类的信息,及动态调用

本文会从以下几个方面讲起

① 反射的简单解释

② java反射的API接口 及 demo

③ 反射的优缺点、应用场景

一、什么是反射?

java反射:在程序运行中动态获取类的信息,及动态调用对象的方法,这就是java反射

二、java反射的API接口

常用API接口规律  

getXX() : 获取类本身 及父类的public属性、方法等

getDeclaredXX() :  获取类本身的所有私有保护属性、方法等

getDeclaredXX(String name) : 获取类本身的指定name的私有、保护属性、方法等(getDeclaredConstructors 较特殊, 还可以获取public)

以下demo涉及到的类先给出咯

package test.reflect;

// 父类
public abstract class Vehicle {
    
    public String superField = "父类属性";
    
    private String superPrivateField = "父类私有属性";
    
    protected String superProtectedField = "父类保护属性";

    public abstract void run();
    
    private void superPrivateMethod() {
        
    }
    
    protected void superProteMethod() {
        
    }
}

// 飞机子类
package test.reflect;

public class Airplane extends Vehicle {

    private String name;

    private int price;
    
    public String publicField;
    
    protected String protectedField;
    
    private Airplane() {
        System.out.println("Airplane 构造函数");
    }
    
    public Airplane(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public void run() {

        System.out.println("春节,坐飞机飞回家~~~");
    }
    
    protected void protectedMethod() {
        
    }
    
    private void privateMethod() {
        
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

}
// 高铁子类
package test.reflect;

public class HighSpeedTrain extends Vehicle {

    private String name;

    private int price;

    public void run() {

        System.out.println("春节,坐高铁溜回家~~~");
    }
    
    private HighSpeedTrain() {
        
    }
    
    protected HighSpeedTrain(String name) {
        
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

}

① 使用反射构建对象

1 private static void demo2() throws Exception {
2         
3         Class.forName("test.reflect.Airplane").newInstance();
4         
5         Airplane.class.newInstance();
6         
7         
8         Airplane.class.getDeclaredConstructor(new Class[]{}).newInstance(); // new Class[]{} 使用无惨构造函数
9     }

所有类都是Class对象, 获取class 有以下三种

Class.forName(包名+类名)

xx.class

xx.getClass

②  获取属性 

getFields() : 获取父子类的所有public属性

getDeclaredFields() : 获取子类的所有private\protected属性

demo如下 : 

private static void demo3() throws Exception {
        //  获取父子类的所有public属性
        Field[] fields = Airplane.class.getFields();
        for(Field f : fields) {
            print(f.getName());
        }
        // 获取子类的所有private\protected属性
        Field[] fields2 = Airplane.class.getDeclaredFields();
        for(Field f : fields2) {
            print(f.getName());
        }
        // 获取指定属性名的属性
        Field f = Airplane.class.getDeclaredField("name");
        print(f.getName());
    }


结果

 1 -------getFields-------
 2 
 3 publicField
 4 
 5 superField
 6 
 7 -------getDeclaredFields-------
 8 
 9 name
10 
11 price
12 
13 publicField
14 
15 protectedField
16 
17 --------getDeclaredField(String)------
18 
19 name
View Code

 

③ 获取方法 

getMethods() : 获取父子类的所有public方法

getDeclaredMethods() : 获取子类的所有private\protected方法

demo如下 : 

    private static void demo4() throws Exception {

        Method[] methods = Airplane.class.getMethods();
        for(Method m : methods) {
            print(m.getName());
        }
        
        
        Method[] methods2 = Airplane.class.getDeclaredMethods();
        for(Method m : methods2) {
            print(m.getName());
        }
        
        
        Method m = Airplane.class.getDeclaredMethod("getName");
        print(m.getName());
        
    }

结果 :

 1 ------getMethods--------
 2 run
 3 getName
 4 setName
 5 getPrice
 6 setPrice
 7 wait
 8 wait
 9 wait
10 equals
11 toString
12 hashCode
13 getClass
14 notify
15 notifyAll
16 ------getDeclaredMethods--------
17 run
18 getName
19 setName
20 protectedMethod
21 privateMethod
22 getPrice
23 setPrice
24 --------getDeclaredMethod------
25 getName
View Code

 

④  获取构造函数(和前面有所区别,指类本身的构造函数,不包括父类)

getConstructors() : 获取public构造函数

getDeclaredConstructors() : 获取子类的所有private\protected\public构造函数 (注意 : 这里还能获取public的, 和 getDeclaredFields getDeclaredMethods 不同)

demo如下 :

Airplane构造函数是public修饰
private static void demo5() throws Exception {
        
        Constructor[] cOnstructors= Airplane.class.getConstructors();
        for(Constructor c : constructors) {
            print(c.getName());
        }
        
        System.out.println("--------------");
        Constructor[] constructors2 = Airplane.class.getDeclaredConstructors();
        for(Constructor c : constructors2) {
            print(c.getName());
        }
        
        System.out.println("--------------");
        Constructor c = Airplane.class.getDeclaredConstructor(new Class[]{String.class, int.class});
        print(c.getName());
        
    }
// 结果
-------getConstructors-------
test.reflect.Airplane
-------getDeclaredConstructors-------
test.reflect.Airplane
test.reflect.Airplane
-------getDeclaredConstructor(Class)-------
test.reflect.Airplane

HighSpeedTrain构造函数是private protected修饰
private static void demo6() throws Exception {
        
        System.out.println("------getConstructors--------");
        Constructor[] cOnstructors= HighSpeedTrain.class.getConstructors();
        for(Constructor c : constructors) {
            print(c.getName());
        }
        
        System.out.println("------getDeclaredConstructors--------");
        Constructor[] constructors2 = HighSpeedTrain.class.getDeclaredConstructors();
        for(Constructor c : constructors2) {
            print(c.getName());
        }
    }
// 结果
------getConstructors--------
------getDeclaredConstructors--------
test.reflect.HighSpeedTrain
test.reflect.HighSpeedTrain

 

  三、java 反射的优缺点

① 优点 :

  • 在运行时检测对象的类型;
  • 动态构造某个类的对象;
  • 检测类的属性和方法;
  • 任意调用对象的方法;
  • 修改构造函数、方法、属性的可见性;
  • 以及其他。

② 缺点 :性能下降 . 由于反射涉及动态解析类型, 所以使用反射构建对象 比 直接构造对象性能差了一两个数量级

    private static void demo7() throws Exception {
        
        long start = System.currentTimeMillis();
        for(int i = 0; i <10000; i++) {
            Airplane a = new Airplane();
        }
        System.out.println(System.currentTimeMillis() - start);
        
        start = System.currentTimeMillis();
        for(int i = 0; i <10000; i++) {
            Airplane a2 = Airplane.class.getDeclaredConstructor().newInstance();
        }
        System.out.println(System.currentTimeMillis() - start);
    }
// 结果
4
54

 

四、反射应用场景

① junit test, 使用注解@Test , 底层无非是使用反射来获取加了Test的注解标识,从而获取到测试方法。

② spring aop思想, spring 加载bean xml 配置文件, 使用 Class.forName(String beanName) 动态构造bean, 也都是反射的经典例子。

 


推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
author-avatar
手机用户2702938100
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有