Java基础笔记-反射及应用

反射:

动态获取字节码文件对象(Person.class),并对其成员进行运行。

动态获取字节码文件对象的方式:

1:任何一个对象都是由字节码文件对象创建的,所以任何一个对象都可以得到自己的字节码文件对象

那么这个功能应该定义在Object中,所以使用 getClass()

需要先new对象

  2:每种数据类型都有一个 静态的class 属性,通过该属性可以得到字节码文件对象
    不需要new对象,但是需要Person类存在

  3:Class类提供了一个静态的forName(String str)方法
    只需要提供字符串形式的包名+类名
1.
Person person1 = new Person();//先加载Person.class到方法区
Class<? extends Person> claz1 = person1.getClass();//得到了Person.class
Person person2 = new Person();
Class<? extends Person> claz2 = person2.getClass();//得到了 Person.class
System.out.println(claz1==claz2);//true
---->字节码文件只加载一次到方法区,所以两次得到的是同一个

2.
Class<Person> claz1 = Person.class;
3.
Class<?> claz1 = Class.forName("com.reflect.Person");

动态获取字节码文件对象,并创建对象:

1)调用无参构造方法创建对象

//当无参的构造方法不存在时,会发生InstantiationException
    //当构造方法的权限过低时,会发生IllegalAccessException
    public static void createObj1() throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        //Person person = new Person();
        //获取字节码文件对象---Person.class
        Class<?> claz = Class.forName("com.reflect.Person");
        //使用Class提供的newInstance()方法创建Person类型的对象
        Object obj = claz.newInstance();//使用无参的构造方法创建对象
        Person person = (Person)obj;
        System.out.println(person);
}

2)使用有参数的构造方法创建对象

public static void createObj2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {   //Person person = new Person("小红",20);
        //获取字节码文件对象---Person.class
        Class<?> claz = Class.forName("com.reflect.Person");
        //得到构造方法所属的Constructor类型的对象
        Constructor<?> constructor = claz.getConstructor(String.class,int.class);
        //使用构造方法创建对象--使用Constructor提供的创建对象的功能
        Person person =(Person)constructor.newInstance("小红",20);
        System.out.println(person);
}

3)动态创建对象并给属性赋值

Class<?> claz = Class.forName("com.reflect.Person");
//得到属性name所属的 Field类型的对象
//Field field = claz.getField("name");//只能获取权限是public 的属性
//System.out.println(field);//NoSuchFieldException
Field field = claz.getDeclaredField("name");
//因为name是非静态属性,所以必须通过对象访问,所以先创建对象
Object obj = claz.newInstance();
//设置name属性为可访问的
field.setAccessible(true);// 该方法是从父类中继承的
//使用Field类提供的赋值功能,给属性赋值
field.set(obj, "小红");
System.out.println(obj);

4)调用静态方法

public static void method3() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");

         ///获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("function", null);
         //执行方法
         method.invoke(null, null);
}

5)通过对象调用无参方法

public static void method1() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        // Person person = new Person();person.show();
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");
         //获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("show", null);
         //show()属于非静态方式,需要对象去调用
         Object obj = claz.newInstance();
         //执行方法
         method.invoke(obj, null);
}

6)通过对象调用有参方法

//调用带参的方法
public static void method2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
        //获取字节码文件对象---Person.class
         Class<?> claz = Class.forName("com.reflect.Person");
       //获取被调用的方法所属的 Method类型的对象
         Method method = claz.getMethod("fun", String.class);
         //fun()属于非静态方式,需要对象去调用
         Object obj = claz.newInstance();
         //执行方法
         method.invoke(obj, "hello");
}

反射应用:

这里有一台笔记本,刚开始只有外设鼠标。后来增加键盘、摄像头等等。

笔记本有running方法和use方法.外设都有open和close方法

public class NoteBook {
    public void runing(){
        System.out.println("电脑运行");
    }
    public void useKeyBoard(KeyBoard kb){
        if(kb!=null){
            kb.open();
            kb.close();
        }
    }
}
调用:
NoteBook noteBook = new NoteBook();
noteBook.runing();
KeyBoard keyBoard = new KeyBoard ();
noteBook.use(keyBoard );

如果添加外设鼠标呢?

NoteBook又得添加一个useMouse(Mouse mouse){..}方法,如果再添加外设的话,还得添加相应的方法。

当然,这里很容易解决,定义一个借口Usb.

interface Usb {
    public void open();
    public void close();
}

然后让外设去实现这个接口,

在NoteBook里面只用定义一个

useUsb(Usb usb){
    usb.open();
    usb.close();
}
在主程里调用:
Usb keyBoard = new KeyBoard ();
noteBook.useUsb(keyBoard );
Usb mouse = new Mouse();
noteBook.useUsb(mouse);

如果还要添加外设,只用添加相应的类并实现Usb接口即可,那么问题来了,主程序里面又得new新的对象,调用相同的语句。

解决方法就可以用反射了:

1.把所有的外设添加到一个配置文件中

usb1=com.reflect.test.KeyBoard

usb2=com.reflect.test.Mouse

2.主程序里调用

Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("config\\config.properties");
properties.load(fileInputStream);
for(int i=1;i<=properties.size();i++)
{
       String value properties.getProperty("usb"+i);
       Class<?> claz = Class.forName(value);
       Object obj = claz.newInstance();
       Usb usb = (Usb)obj;
       noteBook.useUsb(usb);
}

–>添加外设只用在配置文件中添加,主程序调用不用修改

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 22:03:46

Java基础笔记-反射及应用的相关文章

Java基础笔记 – Annotation注解的介绍和使用 自定义注解

Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Annotation的工作原理:2.@Override注解:3.@Deprecated注解:4.@SuppressWarnings注解:5.自定义注解:5.1.添加变量:5.2.添加默认值:5.3.多变量使用枚举:5.4.数组变量:6.设置注解的作用范围:6.1.在自定义注解中的使用例子:7.使用反射读取R

[Java基础笔记]数组

Java基础笔记 定义数组: int[] numbers = new int[100]; //方法一 double[] num = new double[10]; int[][] a = new int[2][5]; 通过new创建的数组,元素默认值为0(0.0) int[] scores = {5,4,33,12,46}; //方法二 int[][] a = { //位数不足,自动补0 {5,3,2,1,6}, {10,12,14,15}, }; 数组特性:存储的都是同类型数据:长度定义后不可

java 基础笔记 基本数据类型对象包装类

基本数据类型对象包装类: 为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操作. 用于描述该对象的类就称为基本数据类型对象包装类. 基本数据类型 包装类 byte Byte short Short int Integer long Long float Float double Double char   Character boolean Boolean 该包装对象主要用于基本类型和字符串之间的转换. 基本类型-->字符串 1.基本类型数据+"&quo

【转】Java基础笔记 – 枚举类型的使用介绍和静态导入--不错

原文网址:http://www.itzhai.com/java-based-notes-introduction-and-use-of-an-enumeration-type-static-import.html#1.2.values方法的使用: Java基础笔记 – 枚举类型的使用介绍和静态导入 本文由arthinking发表于4年前 | Java基础 | 暂无评论 |  被围观 8,332 views+ 1.枚举(Enum):1.1.枚举类型中的两个静态方法:1.2.values方法的使用:

黑马程序员----java基础笔记中(毕向东)

<p>------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! -------</p><p> </p><p>笔记一共记录了毕向东的java基础的25天课程,分上.中.下</p><p>本片为中篇,涵盖11-20天课程</p&

JAVA基础知识|反射

一.理解反射 1.1.基础概念 反射:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. "运行状态",如何理解? "运行状态"体现了反射的应用场景,当一些类,不需要提前加载进JVM内存,而是在运行时根据需要进行加载的时候,就可以通过反射进行动态加载 1.2.如何理解反射? 学习过java的童鞋,肯定对spring.hibernate一

Java基础之—反射

反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))   一.反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 要想解剖一个类,必须先要获取到该类的字节码文件对象.而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对

【转】Java基础之—反射

本文章来源:https://blog.csdn.net/sinat_38259539/article/details/71799078.感谢敬业的小码哥的总结. 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一.反射的概述JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反

Java基础增强-反射机制

1 反射机制简介 Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法.这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制.反射被视为动态语言的关键. 反射这一概念最早由编程开发人员Smith在1982年提出,主要指应用程序访问.检测.修改自身状态与行为的能力.这一概念的提出立刻吸引了编程界的极大关注,各种研究工作随之展开,随之而来引发编程革