2020-12-07 java零基础开始之java反射

目录

 

java反射机制(reflection)

为什么需要使用

如何获得某个class文件对应的class对象:

使用步骤

获取目标类型的class对象(四种方式)

方法一:Object.getClass();

方法二:T.class语法

方法三:Static method Class.fotName

方法四:TYPE语法

实例应用讲解

1:获取类的属性和赋值

2:利用反射调用类的构造函数

3:调用类对象的方法

反射中动态创建数组


java反射机制(reflection)

简单的说,反射机制就是指程序在运行时可以获取自身的信息!!!

为什么需要使用

(比如开发一个文本编辑器:支持txt,pdf,doc三种模式,我们将txt,pdf,doc定义为三个子模块)

静态编译:一次性编译的时候将所有的模块都编译进去。

(我想看个txt,点击图标后,三个模块全部加载到系统,另外两个模块并未使用,所以占用了系统资源)

动态编译: 按需要编译你用到的模块,并不需要一次性全部编译出来。

(我想看那个,就加载判断属于什么格式就加载那个格式,其他的两个模块并未使用,这样编译速度加快,节省系统资源,利于今后拓展


 

如何获得某个class文件对应的class对象:

1.类名.class

2.对象.getClass() --Object类提供

3.Class.forName("包名.类名")

//例如有一个Person对象
package cn.mini.reflect.test;
import org.junit.jupiter.api.Test;
​
public class ClassTest {
    @Test
    /**
     * 获得Class对象 1.通过类名.class 2.对象.getClass() 3.Class.forName();
     */
    public void demo1() throws ClassNotFoundException {
        // 1.类名.class方式
        Class class1=Person.class;
        // 2.通过对象.getClass()方式
        Person person = new Person();
        Class class2 = person.getClass();
        // 3.Class类forName();获得(推荐,因为使用反射一般都不会知道对象的)
        Class class3=Class.forName("cn.mini.reflect.test.Person");
    }
}
//例如有一个Person对象
package cn.mini.reflect.test;
import org.junit.jupiter.api.Test;
​
public class ClassTest {
    @Test
    /**
     * 获得Class对象 1.通过类名.class 2.对象.getClass() 3.Class.forName();
     */
    public void demo1() throws ClassNotFoundException {
        // 1.类名.class方式
        Class class1=Person.class;
        // 2.通过对象.getClass()方式
        Person person = new Person();
        Class class2 = person.getClass();
        // 3.Class类forName();获得(推荐,因为使用反射一般都不会知道对象的)
        Class class3=Class.forName("cn.mini.reflect.test.Person");
    }
}

使用步骤

1.获取目标类型的Class对象

2.通过获取的class对象获取Constructer类对象,Method类对象,Filed类对象

3.通过上面获取的三种不同对象分别获取累的构造函数,方法,属性的具体信息。

 


获取目标类型的class对象(四种方式)

方法一:Object.getClass();

//方法一:Object.getClass(); Boolean carson = true; 
Class<?> classType = carson.getClass(); 
// Object类中的getClass()返回一个Class类型的实例 
System.out.println(classType); // 输出结果:class java.lang.Boolean  

方法二:T.class语法

// T = 任意Java类型(泛型)
  Class<?> classType = Boolean.class; 
  System.out.println(classType); // 输出结果:class java.lang.Boolean  

方法三:Static method Class.fotName

Class<?> classType = Class.forName("java.lang.Boolean"); 
  // 使用时应提供异常处理器
 System.out.println(classType);  // 输出结果:class java.lang.Boolean  

方法四:TYPE语法

  Class<?> classType = Boolean.TYPE; 
  System.out.println(classType);  // 输出结果:boolean  

 


实例应用讲解

1:获取类的属性和赋值

项目结构:

package test;
public class Student {
    public Student() {
        System.out.println("创建了一个Student实例");
    }
    private String name;
}
package test;
import java.lang.reflect.Field;
​
class demo{
    public static void main(String[] args) {
        //获取student的class对象
        Class<Student> studentClass = Student.class;
        try {
            //通过获取到的对象实例化对象
            Student student = studentClass.newInstance();
            //通过class对象获取name属性
            Field f = studentClass.getDeclaredField("name");
            //设置私有访问权限(true为私有权限可以访问,否则相反)
            f.setAccessible(true);
            //通过实例化的对象设置name属性值
            f.set(student,"minibar");
            //输出测试结果
            System.out.println(f.get(student));
        } catch (NoSuchFieldException | IllegalAccessException |
                 InstantiationException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

2:利用反射调用类的构造函数

项目结构:

package test2;
public class Student {
    // 无参构造函数
    public Student() {
        System.out.println("调用了无参构造函数");
    }
    // 有参构造函数
    public Student(String str) {
        System.out.println("调用了有参构造函数: "+str);
    }
    private String name;
}
package test2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
​
public class test {
    public static void main(String[] args) {
        //获取Student的class对象
        Class<Student> studentClass1 = Student.class;
        try {
            //通过构造器获取class对象
            Constructor<Student> constructor = studentClass1.getConstructor();
            //通过class对象获取Constructor类对象(调用的是无参构造方法)
            Student student = constructor.newInstance();
            //通过class对象获取Constructor对象 (调用的是有参构造方法)
            Constructor<Student> constructor1 = studentClass1.getConstructor(String.class);
            Student student1 = constructor1.newInstance("hello");
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

3:调用类对象的方法

项目结构:

package test2;
public class Student {
    public Student() {
        System.out.println("创建了一个Student实例");
    }
    // 无参数方法
    public void setName1 (){
        System.out.println("调用了无参方法:setName1()");
    }
    // 有参数方法
    public void setName2 (String str){
        System.out.println("调用了有参方法:setName2(String str):" + str);
    }
}
package test2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
​
public class test {
    public static void main(String[] args) {
        //获取Student的class对象
        Class<Student> studentClass = Student.class;
        try {
            //实例化Student对象
            Student student = studentClass.newInstance();
            //获取class对象获取方法setName1的Method对象
            Method setName1 = studentClass.getMethod("setName1");
            setName1.invoke(student);
            //获取class对象获取方法setName2的Method对象
            Method setname2 = studentClass.getMethod("setName2", String.class);
            setname2.invoke(student,"hello Method");
        } catch (InstantiationException | IllegalAccessException |
                NoSuchMethodException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
​

运行结果:

反射中动态创建数组

通过Array.newinstance()方法

// Array.java
public static Object newInstance(Class<?> componentType, int... dimensions)
        throws IllegalArgumentException, NegativeArraySizeException {
        return multiNewArray(componentType, dimensions);
    }
//比如我们呢要创建 int [][] ints = new int[2][3];
第一个参数(数组类元素类型)第二个(相应维度中数组的长度)
Array.newInstance(int.class,2,3);

Array的读取与赋值

import java.lang.reflect.Array;
​
public class ArrayList {
    /**main*/
    public static void main(String[] args) throws Exception {
        ArrayList testArray = new ArrayList();
        testArray.testOneObject();
        testArray.testOne();
        testArray.testTwo();
    }
​
    /**放置数据
     * @throws ClassNotFoundException **/
    public void testOneObject() throws ClassNotFoundException{
        Object object = Array.newInstance(Object.class,10);
        Array.set(object,3,"00000");
        System.out.println(Array.get(object,3));
    }
​
    /**一维素组*/
    public void testOne() throws ClassNotFoundException{
        Class<?> classType = Class.forName("java.lang.String");
        Object object = Array.newInstance(classType,10);  //数组0,9
        Array.set(object,5,"11111");
        System.out.println(Array.get(object, 5));
        System.out.println(Array.getLength(object));
    }
​
    /**二维数组*/
    public void testTwo() throws ClassNotFoundException {
        Class<?> classType = Class.forName("java.lang.String");
        Object object = Array.newInstance(classType, 10,10);  //数组0,9
        Array.set(Array.get(object,5),5,"22222");  //[5][5] 为"123",先获取一维,在通过一维获取二维的数据
        System.out.println(Array.get(Array.get(object,5),5));
    }
}

运行结果:

 


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值