java基础-9 反射

反射

  • 类加载器

  • 类加载

类加载的描述

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。如果不出现意外情况,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或者类初始化

类的加载

  1. 就是指将class文件读入内存,并为之创建一个 java.lang.Class 对象
  2. 任何类被使用时,系统都会为之建立一个 java.lang.Class 对象类的连接

/*
    ClassLoader 中的两个方法
        static ClassLoader getSystemClassLoader​():返回用于委派的系统类加载器
        ClassLoader getParent​():返回父类加载器进行委派
 */
public class Test {
    public static void main(String[] args) {
        //static ClassLoader getSystemClassLoader​():返回用于委派的系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);  //AppClassLoader

        //ClassLoader getParent​():返回父类加载器进行委派
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent); //PlatformClassLoader

        ClassLoader c3 = parent.getParent();
        System.out.println(c3); //null
    }
}

/*
jdk.internal.loader.ClassLoaders$AppClassLoader@78308db1
jdk.internal.loader.ClassLoaders$PlatformClassLoader@2d98a335
null
*/
  • 反射

  • 反射的概述

是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

/*
    三种方式获取Class对象
        1:使用类的class属性来获取该类对应的Class对象。举例:Student.class将会返回Student类对应的Class对象
        2:调用对象的getClass()方法,返回该对象所属类对应的Class对象
            该方法是Object类中的方法,所有的Java对象都可以调用该方法
        3:使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,该字符串参数的值是某个类的全路径,也就是完整包名的路径
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //使用类的class属性来获取该类对应的Class对象
        Class<Student> stuClass = Student.class;
        System.out.println(stuClass);
        Class<Student> stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);
        System.out.println("----------------------");

        //调用对象的getClass()方法,返回该对象所属类对应的Class对象
        Student stu = new Student();
        Class<? extends Student> stuClass3 = stu.getClass();
        System.out.println(stuClass == stuClass3);
        System.out.println("----------------------");

        //使用Class类中的静态方法forName(String className)
        Class<?> stuClass4 = Class.forName("com.Reflect.Student");
        System.out.println(stuClass == stuClass4);
    }
}

/*
class com.Reflect.Student
true
----------------------
true
----------------------
true
*/
  • 反射获取构造方法并使用

Class类获取构造方法对象的方法     方法分类

方法名

说明

Constructor<?>[] getConstructors()

返回所有公共构造方法对象的数组

Constructor<?>[] getDeclaredConstructors()

返回所有构造方法对象的数组

Constructor getConstructor(Class<?>... parameterTypes)

返回单个公共构造方法对象

Constructor getDeclaredConstructor(Class<?>...

parameterTypes)

返回单个构造方法对象

package com.Reflect;

public class Student {
    //成员变量:一个私有,一个默认,一个公共
    private String name;
    int age;
    public String address;

    //构造方法:一个私有,一个默认,两个公共
    public Student() {
    }

    private Student(String name) {
        this.name = name;
    }

    Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    //成员方法:一个私有,四个公共
    private void function() {
        System.out.println("function");
    }

    public void method1() {
        System.out.println("method");
    }

    public void method2(String s) {
        System.out.println("method:" + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}



/*
    反射获取构造方法并使用获取对象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> stuClass = Class.forName("com.Reflect.Student");

        //Constructor<?>[] getConstructors​() 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
        Constructor<?>[] publicConstructors = stuClass.getConstructors();   //公共构造方法数组
        for (Constructor<?> stuCon : publicConstructors) System.out.println(stuCon);
        System.out.println("------------------");

        //Constructor<?>[] getDeclaredConstructors​() 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组
        Constructor<?>[] allConstructors = stuClass.getDeclaredConstructors();       //所有构造方法数组
        for (Constructor<?> stuCon : allConstructors) System.out.println(stuCon);
        System.out.println("------------------");

        //Constructor提供了一个类的单个构造函数的信息和访问权限 Constructor<?> con = c.getConstructor();
        Constructor<?> stuConstructor = stuClass.getConstructor();
        //T newInstance​(Object... initargs) 使用由此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例
        Object student = stuConstructor.newInstance();
        System.out.println(student);
    }
}

/*
public com.Reflect.Student(java.lang.String,int,java.lang.String)
public com.Reflect.Student()
------------------
public com.Reflect.Student(java.lang.String,int,java.lang.String)
com.Reflect.Student(java.lang.String,int)
private com.Reflect.Student(java.lang.String)
public com.Reflect.Student()
------------------
Student{name='null', age=0, address='null'}
*/

 获取构造方法初始化对象

通过反射获取公共的构造方法并创建对象

/*
    反射获取构造方法并使用获取对象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Constructor提供了一个类的单个构造函数的信息和访问权限 Constructor<?> con = c.getConstructor();
        //public Student(String name, int age, String address)
        Constructor<?> stuConstructor = student.getConstructor(String.class, int.class, String.class);

        //T newInstance​(Object... initargs) 由Constructor对象表示的构造函数来创建和初始化构造函数的声明类的新实例
        Object stu = stuConstructor.newInstance("李茂贞", 25, "岐国");
        System.out.println(stu);
    }
}
/*
Student{name='李茂贞', age=25, address='岐国'}
*/

/*
    暴力反射
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Constructor 提供了一个类的单个构造函数的信息和访问权限 Constructor<?> con = c.getConstructor();
        //反射 私有 构造方法private Student(String name)
        Constructor<?> stuConstructor = student.getDeclaredConstructor(String.class);

        //暴力反射
        //将此反射对象的accessible标志设置为指示的布尔值。 值为true表示反射对象应该在使用Java语言访问控制时抑制检查。 值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
        //public void setAccessible​(boolean flag):值为true,取消访问检查
        stuConstructor.setAccessible(true);

        //T newInstance​(Object... initargs) 由Constructor对象表示的构造函数来创建和初始化构造函数的声明类的新实例
        Object stu = stuConstructor.newInstance("李茂贞");
        System.out.println(stu);
    }
}
/*
Student{name='李茂贞', age=0, address='null'}
*/
  • Class类获取成员变量对象的方法

方法分类

方法名

说明

Field[] getFields()

返回所有公共成员变量对象的数组

Field[] getDeclaredFields()

返回所有成员变量对象的数组

Field getField(String name)

返回单个公共成员变量对象

Field getDeclaredField(String name)

返回单个成员变量对象

Field类用于给成员变量赋值的方法                                                                                

方法名

说明

voidset(Object obj,Object value)

obj对象的成员变量赋值为value

/*
    反射获取成员变量并使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
        //获取Class对象
        Class<?> student = Class.forName("com.Reflect.Student");

        //Field[] getFields​() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段
        Field[] fields1 = student.getFields();
        //Field[] getDeclaredFields​() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段
        Field[] declaredFields = student.getDeclaredFields();
        for (Field fi : declaredFields) System.out.println(fi);
        System.out.println("----------------------------");
        //Field getField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段
        Field address = student.getField("address");
        //Field getDeclaredField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段
        Field name = student.getDeclaredField("name");

        //获取无参构造方法创建对象
        Constructor<?> stuConstructor = student.getConstructor();
        //获取Student类对象
        Object stu = stuConstructor.newInstance();


        //Field提供有关类或接口的单个字段的信息和动态访问
        //void set​(Object obj, Object value) 将指定的对象参数中由此 Field对象表示的字段设置为指定的新值
        address.set(stu, "岐国");  //addressField.set(stu, "岐国"); //给stu的成员变量address赋值为岐国
        name.setAccessible(true);
        name.set(stu, "李茂贞");  //IllegalAccessException,前面添加 name.setAccessible(true);暴力反射
        System.out.println(stu);
    }
}
/*
private java.lang.String com.Reflect.Student.name
int com.Reflect.Student.age
public java.lang.String com.Reflect.Student.address
----------------------------
Student{name='李茂贞', age=0, address='岐国'}
*/

/*
    反射获取成员变量并使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
        Class student = Class.forName("com.Reflect.Student");
        Constructor<?> stuConstructor = student.getConstructor();
        Object stu = stuConstructor.newInstance();

        //name = "李茂贞"
        Field name = student.getDeclaredField("name");
        name.setAccessible(true);
        name.set(stu, "李茂贞");

        //age = 25
        Field age = student.getDeclaredField("age");
        age.setAccessible(true);
        age.set(stu, 25);

        //address = "岐国"
        Field address = student.getDeclaredField("address");
        address.setAccessible(true);
        address.set(stu, "岐国");

        System.out.println(stu);
    }
}
/*
Student{name='李茂贞', age=25, address='岐国'}
*/
  • 反射获取成员变量并使用练习

Class类获取成员方法对象的方法     方法分类

方法名

说明

Method[] getMethods()

返回所有公共成员方法对象的数组,包括继承的

Method[] getDeclaredMethods()

返回所有成员方法对象的数组,不包括继承的

Method getMethod(String name, Class<?>...

parameterTypes)

返回单个公共成员方法对象

Method getDeclaredMethod(String name, Class<?>...

parameterTypes)

返回单个成员方法对象

/*
    反射获取成员方法并使用
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class student = Class.forName("com.Test.Student");

        //Method[] getMethods​() 返回一个包含 方法对象的数组, 方法对象反映由该 Class对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类
        //获取本类所有父类的公共方法
        //Method[] methods1 = student.getMethods();

        //Method[] getDeclaredMethods​() 返回一个包含 方法对象的数组, 方法对象反映由 Class对象表示的类或接口的所有声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承方法
        Method[] declaredMethods = student.getDeclaredMethods();
        for (Method method: declaredMethods) System.out.println(method);
        System.out.println("---------------------");

        //Method getMethod​(String name, Class<?>... parameterTypes) 返回一个 方法对象,该对象反映由该 Class对象表示的类或接口的指定公共成员方法
        //Method getDeclaredMethod​(String name, Class<?>... parameterTypes) 返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 Class对象
        Method dMethod = student.getDeclaredMethod("method1");

        //获取无参构造方法创建对象
        Constructor stuCon = student.getConstructor();
        Object stu = stuCon.newInstance();

        //在类或接口上提供有关单一方法的信息和访问权限
        //Object invoke​(Object obj, Object... args) 在具有指定参数的指定对象上调用此 方法对象表示的基础方法
        //Object:返回值类型
        //obj:调用方法的对象
        //args:方法需要的参数
        dMethod.invoke(stu);
    }
}

/*
public java.lang.String com.Test.Student.toString()
private void com.Test.Student.function()
public void com.Test.Student.method1()
public java.lang.String com.Test.Student.method3(java.lang.String,int)
public void com.Test.Student.method2(java.lang.String)
---------------------
method
*/

/*
     练习:通过反射实现如下操作
        Student s = new Student();
        s.method1();
        s.method2("林青霞");
        String ss = s.method3("林青霞",30);
        System.out.println(ss);
        s.function();
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class student = Class.forName("com.Test.Student");

        //Student s = new Student();
        Constructor stuCon = student.getConstructor();
        Object stu = stuCon.newInstance();

        //s.method1();
        Method method1 = student.getMethod("method1");
        method1.invoke(stu);

        //s.method2("林青霞");
        Method method2 = student.getMethod("method2", String.class);
        method2.invoke(stu, "李茂贞");

//        String ss = s.method3("林青霞",30);
//        System.out.println(ss);
        Method method3 = student.getMethod("method3", String.class, int.class);
        Object rensult = method3.invoke(stu, "李茂贞", 25);
        System.out.println(rensult);
        System.out.println((String)rensult);

        //s.function();    //private void function()
//        Method m4 = c.getMethod("function"); //NoSuchMethodException: com.itheima_02.Student.function()
        Method function = student.getDeclaredMethod("function");
        function.setAccessible(true);
        function.invoke(stu);
    }
}

/*
method
method:李茂贞
李茂贞,25
李茂贞,25
function
*/
  • 反射练习之越过泛型检查

/*
    练习1:我有一个ArrayList<Integer>集合,现在我想在这个集合中添加一个字符串数据,如何实现?
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //创建集合
        ArrayList<Integer> array = new ArrayList<>();

        array.add(10);
        array.add(50);
        array.add(90);

        System.out.println(array);

        //获取Classd对象
        Class<? extends ArrayList> arrayClass = array.getClass();
        Method add = arrayClass.getDeclaredMethod("add", Object.class);
        
        add.invoke(array, "hello");
        add.invoke(array, "reflect");
        
        System.out.println(array);
    }
}

/*
[10, 50, 90]
[10, 50, 90, hello, reflect]
*/
  •  运行配置文件中指定类的指定方法

/*
    练习2:通过配置文件运行类中的方法
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
/*        Teacher tea = new Teacher();
        tea.teach();

        Student stu = new Student();
        //private void study
        */
        /*
            class.txt
            className=xxx
            methodName=xxx
         */
        //加载数据
        FileReader fr = new FileReader("E:\\work_space\\java_work\\java_test\\src\\com\\Test\\conf.txt");
        Properties prop = new Properties();
        prop.load(fr);
        System.out.println(prop);

        //通过反射来调用方法
        Class obClass = Class.forName(prop.getProperty("className"));
        Constructor constructor = obClass.getConstructor();
        Object o = constructor.newInstance();

        Method method = obClass.getDeclaredMethod(prop.getProperty("methodName"));
        method.setAccessible(true);
        method.invoke(o);

        //通过反射来调用方法
        Class obClass2 = Class.forName(prop.getProperty("className2"));
        Constructor constructor2 = obClass2.getConstructor();
        Object o2 = constructor2.newInstance();

        Method method2 = obClass2.getDeclaredMethod(prop.getProperty("methodName2"));
        method2.setAccessible(true);
        method2.invoke(o2);
    }
}

/*
{methodName=teach, methodName2=study, className=com.Test.Teacher, className2=com.Test.Student}
老师教学!
学生学习!
*/
  • 模块化

模块化概述【理解】                                                                               

Java语言随着这些年的发展已经成为了一门影响深远的编程语言,无数平台,系统都采用Java语言编写。但是,伴随着发展,Java也越来越庞大,逐渐发展成为一门臃肿的语言。而且,无论是运行一个大型的软件系统,还是运行一个小的程序,即使程序只需要使用Java的部分核心功能, JVM也要加载整个JRE环境。 为了给Java“瘦身,让Java实现轻量化,Java 9正式的推出了模块化系统。Java被拆分为N多个模块,并允许Java程序可以根据需要选择加载程序必须的Java模块,这样就可以让Java以轻量化的方式来运行

其实,Java 7的时候已经提出了模块化的概念,但由于其过于复杂,Java 7Java 8都一直未能真正推出,直到Java 9才真正成熟起来。对于Java语言来说,模块化系统是一次真正的自我革新,这种革新使得古老而庞大Java语言重新焕发年轻的活力

 

package com.toroidal01;

public class Studnet {
    public void study(){
        System.out.println("学生学习!");
    }
}


module myOne {
    exports com.toroidal01;
}

module myTow {
    requires myOne;
}


package com.toroidal;

import com.toroidal01.Studnet;

public class Test {
    public static void main(String[] args) {
        Studnet stu = new Studnet();
        stu.study();
    }
}
  • 模块服务的基本使用

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章