欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java-进阶-day15-反射

程序员文章站 2022-06-18 10:35:21
...

Java进阶-day15-反射

今日内容

  • 反射
  • 模块化

类加载器

1.1 类加载【理解】

  • 类加载的描述
  • 类加载器
    Java-进阶-day15-反射

    • 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过 “类的加载”,“类的连接”,

      • “类的初始化” 这三个步骤来对类进行初始化。
    • 如果不出现意外情况,JVM将会连续完成这三个步骤,
      以有时也把这三个步骤统称为类加载或者类初始化.

    • 一个类的生命周期包括了 “加载”、“验证”、“准备”、“解析”、“初始化”、“使用”、“卸载” 这七个阶段,
      一般我们只研究前五个阶段,这五个阶段又可以分为 “加载”、“连接(准备,验证,解析)” 、 “初始化”

  • 类的加载: 加载二进制数据
  • 类的加载主要做三件事情:
    1. 找到类文件(通过类的全限定名来获取定义此类的二进制字节流)
    • 首先会根据各种途径(比如网络下载、数据库提取、从jar,zip中读取等)获取类的二进制数据
    1. 放入方法区(将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构)
    • 把获取到的二进制数据读入内存,存储在运行时数据区的方法区,
      这些二进制数据所代表的存储结构会被转化为方法区中运行时的数据结构
    1. 开个入口(生成一个代表此类的java.lang.Class对象,作为访问方法区这些数据结构的入口)
    • 在方法区中创建相应的class对象(这里的class对象与平时所说的对象是不一样的,
      当使用new创建实例对象时,就会通过class对象在堆中创建实例对象)用来封装保存在方法区内的数据结构
  • 类的连接
  • 验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致

    • 文件格式验证:验证字节流是否符合class文件的规范,确保输入的字节流能正确解析并存储到方法区
    • 元数据验证:对字节码描述的信息进行语义分析,保证其描述的信息符合规范要求。
    • 字节码验证:这个阶段是比较复杂的,通过数据流和控制流分析,对类的方法体进行校验,确保程序的合法性
    • 符号引用验证:这里的符号引用不单单指类的,也包括方法。发生在符号引用转为直接引用的时候,也就是解析阶段, 对常量池中各种符号引用的信息进行匹配性校验,确保解析动作正确执行
  • 准备阶段:将为静态变量和静态常量分配内存,并赋值

    • 需要注意的是:
      • 静态变量只会给默认值。

        • 例:public static int value = 123; // 此时赋给value的值是0,不是123。
      • 静态常量(static final修饰的)则会直接赋值。

        • 例:public static final int value = 123; // 此时赋给value的值是123。
  • 解析阶段:将类的二进制数据中的符号引用替换为直接引用

  • 类的初始化
  • 类的初始化的主要工作是为静态变量赋程序设定的初值。

  • 类的初始化步骤

    • 假如类还未被加载和连接,则程序先加载并连接该类
    • 假如该类的直接父类还未被初始化,则先初始化其直接父类
    • 假如类中有初始化语句,则系统依次执行这些初始化语句
    • 注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1*3
  • 类的初始化时机
  • 创建类的实例 new Student();
  • 调用类的类方法 Math.abs();
  • 访问类或者接口的类变量,或者为该类变量赋值 InterFace.NUMBER;
  • 使用反射方式来强制创建某个类或接口对应的对象 Class
  • 初始化某个类的子类 new Dog(); Animal
  • 直接使用 java.exe 命令来运行某个主类

1.2 类加载器【理解】

1.2.1 类加载器的作用

  • 负责将class文件加载到内存中,并为之生成对应的 java.lang.Class 对象。
    虽然我们不用过分关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行!

1.2.2 JVM的类加载机制

  • 全盘负责:就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入

  • 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类

  • 缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存储到缓存区

  • 什么是双亲委派机制:

  1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,
    如果已经加载则直接返回原来已经加载的类。每个类加载器都有自己的加载缓存,
    当一个类被加载了以后就会放入缓存,等下次加载的时候就可以直接返回了。

  2. 当前classLoader的缓存中没有找到被加载的类的时候,委托父类加载器去加载,
    父类加载器采用同样的策略,首先查看自己的缓存,然后委托父类的父类去加载,
    一直到bootstrp ClassLoader.

  3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,
    并将其放入它自己的缓存中,以便下次有加载请求的时候直接返回。

  • 这样做的好处是什么?
  1. 避免重复加载。当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
  2. 为了安全。避免核心类,比如String被替换。

1.2.3 Java中的内置类加载器(预定义类加载器)

  • 当JVM启动的时候,Java缺省开始使用如下三种类加载器:

    • BootstrapClassLoader:它是虚拟机的内置类加载器,通常表示为null ,并且没有父null

      • 引导类加载器, 用来加载 Java 的核心库,是用原生代码来实现的,
        并不继承自 java.lang.ClassLoader。它负责将jre/lib下面的核心类库.
    • PlatformClassLoader:平台类加载器可以看到所有平台类 ,平台类包括由平台类加载器或其祖先定义的Java SE平台API,其实现类和JDK特定的运行时类

    • SystemClassLoader:它也被称为应用程序类加载器(ApplicationClassLoader) ,与平台类加载器不同。 系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类

    • UserClassLoader:自定义类加载器

    • 类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap

1.2.4 ClassLoader 中的两个方法

  • 方法分类

    • static ClassLoader getSystemClassLoader()返回用于委派的系统类加载器
    • ClassLoader getParent()返回父类加载器进行委派
  • 示例代码

  
public class ClassLoaderDemo {
  public static void main(String[] args) {
      //static ClassLoader getSystemClassLoader():返回用于委派的系统类加载器
      ClassLoader c = ClassLoader.getSystemClassLoader();
      System.out.println(c); //AppClassLoader

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

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

2.反射

2.1反射的概述【理解】

  • 总结:
    • 反射: 在程序运行时期获取各个类(Class),将类的信息封装成相应的(Field,Constructor,Method)对象

    • 类的信息:

      1. 成员变量 Field
      2. 构造方法 Constructor
      3. 成员方法 Method
    • 类的对象 : Class

      • 这些相应的对象都是在Class对象中

2.2 获取Class类对象的三种方式【应用】

  • 总结:

    • 第一种方式 : 做为一个方法的参数进行传递,方法的参数是Class类型
      类名.class 属性
    • 第二种方式 : 方法的参数是一个类名时,可以在方法中使用该方式获取该类名的字节码对象
      对象名.getClass()
    • 第三种方式(推荐) : 通用的方式,经常会将类的全路径,放在一个配置文件中
      类的全路径: 包名 + 类名
      Class.forName(String classNamePath)
  • 示例代码


public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取字节码对象
        // 第一种方式 对象名.getClass
        // 方法的参数是一个类名的时候,获取到这个类的字节码文件
        Student stu = new Student();
        Class clazz1 = stu.getClass();

        // 第二种方式 类名.class
        //  方法的参数是一个Class字节码对象
        Class clazz2 = Student.class;
        method2(Student.class);

        // 第三种方式 Class.forName(String className)
        // 把类的路径存储到配置文件 中
        Class clazz3 = Class.forName("com.itheima.m_code.demo01.Student");

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz1 == clazz3);
    }


    // 第一种方式 对象名.getClass 应用场景
    public static void method1(Student student) {
        Class<? extends Student> aClass = student.getClass();
    }

    // 第二种方式 类名.class应用场景
    public static void method2(Class clazz){
        
    }
}

2.3 反射获取构造方法并使用【应用】

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

  • 方法分类

    • Constructor <?>[] getConstructors()
      • 返回所有public修饰的公共构造方法对象的数组 ,私有的获取不到
    • Constructor<?>[] getDeclaredConstructors()
      • 返回所有构造方法对象的数组 包括私有的
    • Constructor getConstructor(Class<?>… parameterTypes)
      • 返回单个公共构造方法对象
    • Constructor getDeclaredConstructor(Class<?>… parameterTypes)
      • 返回单个构造方法对象

2.3.2 Constructor类用于创建对象的方法

T newInstance(Object…initargs) 根据指定的构造方法创建对象


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

        //Constructor<?>[] getConstructors​() 返回一个包含 Constructor对象的数组, Constructor对象反映了由该 Class对象表示的类的所有公共构造函数
//        Constructor<?>[] cons = c.getConstructors();
        //Constructor<?>[] getDeclaredConstructors​() 返回反映由该 Class对象表示的类声明的所有构造函数的 Constructor对象的数组
        Constructor<?>[] cons = c.getDeclaredConstructors();
        for(Constructor con : cons) {
            System.out.println(con);
        }
        System.out.println("--------");

        //Constructor<T> getConstructor​(Class<?>... parameterTypes) 返回一个 Constructor对象,该对象反映由该 Class对象表示的类的指定公共构造函数
        //Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes) 返回一个 Constructor对象,该对象反映由此 Class对象表示的类或接口的指定构造函数
        //参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象

        // 使用的是无参构造创建对象,选择构造的阶段
        Constructor<?> con = c.getConstructor();


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

//        Student s = new Student();
//        System.out.println(s);
    }
}

2.4 反射获取构造方法并使用练习1【应用】

  • 案例需求

    • 通过反射获取公共的构造方法并创建对象
  • 代码实现

/*
    通过反射实现如下的操作:
        Student s = new Student("林青霞",30,"西安");
        System.out.println(s);
 */
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima.t_code.reflect.itheima_02.Student");

        //public Student(String name, int age, String address)
        //Constructor<T> getConstructor​(Class<?>... parameterTypes)
        Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
        //基本数据类型也可以通过.class得到对应的Class类型

        //T newInstance​(Object... initargs)
        // Object obj = con.newInstance("林青霞", 30, "西安");
        Student obj = (Student) con.newInstance("林青霞", 30, "西安");
        // 如何获取姓名  年龄  地址
        System.out.println(obj.getName());
        System.out.println(obj.getAge());
        System.out.println(obj.getAddress());

        System.out.println(obj);
    }
}

2.5 反射获取构造方法并使用练习2【应用】

  • 案例需求

    • 通过反射获取私有构造方法并创建对象
  • 代码实现

    • 学生类:参见上方学生类

    • 测试类


    /*
     * Constructor <?>[] getConstructors()
     * 返回所有public修饰的公共构造方法对象的数组
     * Constructor<?>[] getDeclaredConstructors()
     * 返回所有构造方法对象的数组
     * Constructor<T> getConstructor(Class<?>... parameterTypes)
     * 返回单个公共构造方法对象
     * Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
     * 返回单个构造方法对象
     */
    public class ConstructorDemo {
        public static void main(String[] args) throws Exception {

            // 获取Student的Class对象
            Class clazz = Class.forName("cn.itcast.domain.Student");
            // 通过简便的方式,创建对象
            // Object obj = clazz.newInstance();
            // System.out.println(obj);

            // 获取所有的public所修饰的构造方法
            // Constructor <?>[] getConstructors()
            // Constructor[] cons = clazz.getConstructors();
            // for (Constructor c : cons) {
            //     System.out.println(c);
            //
            // }

            // 获取所有的构造方法
            /*Constructor[] cons = clazz.getDeclaredConstructors();
            for (Constructor c : cons) {
                System.out.println(c);

            }*/

            // 获取public修饰的指定的无参的构造
            // Constructor con = clazz.getConstructor();
            // System.out.println(con);

            // 获取私有的指定的name的有参构造
            // Constructor con = clazz.getDeclaredConstructor(String.class);
            // System.out.println(con);
            // 暴力反射
            // con.setAccessible(true);

            // 创建对象
            // Object obj = con.newInstance("张三");
            // System.out.println(obj);

            // public Student(String name, int age, String address)
            // Constructor con = clazz.getConstructor(String.class,int.class,String.class);
            // Object obj = con.newInstance("张三",123,"北京");
            // System.out.println(obj);
        }
    }

2.6 反射获取成员变量并使用【应用】

2.6.1 Class类获取成员变量对象的方法

* Field[] getFields()                   返回所有公共成员变量对象的数组  
* Field[] getDeclaredFields()           返回所有成员变量对象的数组      
* Field getField(String name)           返回单个公共成员变量对象        
* Field getDeclaredField(String name)   返回单个成员变量对象            
  • 示例代码

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

void set(Object obj,Object value) 给obj对象的成员变量赋值为value

  • 案例代码:
/*
    反射获取成员变量并使用
 */
public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima.t_code.reflect.itheima_02.Student");
        Object obj = c.newInstance();

        //Field[] getFields​() 返回一个包含 Field对象的数组, Field对象反映由该 Class对象表示的类或接口的所有可访问的公共字段
        //Field[] getDeclaredFields​() 返回一个 Field对象的数组,反映了由该 Class对象表示的类或接口声明的所有字段
//        Field[] fields = c.getFields();
        Field[] fields = c.getDeclaredFields();
        for(Field field : fields) {
            System.out.println(field);
        }
        System.out.println("--------");

        //Field getField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定公共成员字段
        //Field getDeclaredField​(String name) 返回一个 Field对象,该对象反映由该 Class对象表示的类或接口的指定声明字段
        Field addressField = c.getField("address");


        //获取无参构造方法创建对象
        // Constructor<?> con = c.getConstructor();
        // Object obj = con.newInstance();

//        obj.addressField = "西安";

        //Field提供有关类或接口的单个字段的信息和动态访问
        //void set​(Object obj, Object value) 将指定的对象参数中由此 Field对象表示的字段设置为指定的新值
        addressField.set(obj,"西安"); //给obj的成员变量addressField赋值为西安

        System.out.println(obj);



//        Student s = new Student();
//        s.address = "西安";
//        System.out.println(s);
    }
}

2.7 反射获取成员变量并使用练习【应用】

  • 案例需求

    • 通过反射获取成员变量并赋值
  • 代码实现

    • 学生类:参见上方学生类

    • 案例代码:


   /*
    * Field[] getFields()                   返回所有公共成员变量对象的数组
    * Field[] getDeclaredFields()           返回所有成员变量对象的数组
    * Field getField(String name)           返回单个公共成员变量对象
    * Field getDeclaredField(String name)   返回单个成员变量对象

    */
   public class FieldDemo {
       public static void main(String[] args) throws Exception {
           // 获取Student的Class对象
           Class clazz = Class.forName("cn.itcast.domain.Student");
           // 创建对象
           Object obj = clazz.newInstance();
           // Field[] getFields()
           // Field[] fields = clazz.getFields();
           // Field[] getDeclaredFields()
           // Field[] fields = clazz.getDeclaredFields();
           // for (Field field : fields) {
           //     System.out.println(field);
           // }

           Field address = clazz.getField("address");
           // // 给这个变量 address 赋值
           address.set(obj,"东京");
           // // 获取值
           // Object addressObj = address.get(obj);
           // System.out.println(addressObj);
           // System.out.println(obj);

           // Field getDeclaredField(String name)
           Field name = clazz.getDeclaredField("name");
           // 取消访问检查
           name.setAccessible(true);
           name.set(obj,"小苍");

           // 给年龄进行赋值
           Field age = clazz.getDeclaredField("age");
           // 取消访问检查
           age.setAccessible(true);
           age.set(obj,32);

           System.out.println(obj);
       }
   }


2.8 反射获取成员方法并使用【应用】

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

* Method[] getMethods()                                          
  * 返回所有公共成员方法对象的数组,包括继承的  
* Method[] getDeclaredMethods()                                  
  * 返回所有成员方法对象的数组,不包括继承的    
* Method getMethod(String name, Class<?>... parameterTypes)      
  * 返回单个公共成员方法对象                    
* Method getDeclaredMethod(String name, Class<?>... parameterTypes)   
  * 返回单个成员方法对象
* Object invoke(Object obj,Object... args)   
  * 调用obj对象的成员方法,参数是args,返回值是Object类型  
  • 示例代码
/*
    反射获取成员方法并使用
 */
public class ReflectDemo01 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima.t_code.reflect.itheima_02.Student");

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

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

        //获取无参构造方法创建对象
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

//        obj.m();

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

//        Student s = new Student();
//        s.method1();
    }
}

2.9 反射获取成员方法并使用练习【应用】

  • 案例需求

    • 通过反射获取成员方法并调用
  • 代码实现


public class MethodTest {
    public static void main(String[] args) throws Exception {
        // 获取Student的Class对象
        Class clazz = Class.forName("cn.itcast.domain.Student");
        // 创建对象
        Object obj = clazz.newInstance();

        //  public String method3(String s, int i)
        Method method = clazz.getMethod("method3", String.class, int.class);
        //  执行方法
        Object str = method.invoke(obj, "麻生希", 30);
        System.out.println(str);

        System.out.println("~~~~~~~~~~~~~~~~~~~");

        Method method1 = clazz.getDeclaredMethod("method4", String.class, int.class);
        // 暴力反射
        method1.setAccessible(true);
        // 执行方法
        Object o = method.invoke(obj, "波姐", 28);
        System.out.println(o);
    }
}

2.10 反射的案例【应用】

2.10.1 反射练习之越过泛型检查

  • 案例需求

    • 通过反射技术,向一个泛型为Integer的集合中添加一些字符串数据
  • 代码实现


public class Test1 {
    public static void main(String[] args) throws Exception {
        // 泛型在编译时期是有这个泛型的,在运行时期是没有泛型的 --> 泛型擦除
        ArrayList<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        // list.add(123);

        // 获取list的Class对象
        Class clazz = list.getClass();
        // 获取对象中的方法 add
        Method methodAdd = clazz.getMethod("add", Object.class);
        // 运行,添加数据
        methodAdd.invoke(list, 100);
        methodAdd.invoke(list, 200);
        methodAdd.invoke(list, true);

        System.out.println(list);
    }
}

2.10.2 运行配置文件中指定类的指定方法

  • 案例需求

    • 通过反射运行配置文件中指定类的指定方法
  • 代码实现

配置文件:class.txt
className=com.itheima_06.Teacher
methodName=teach
  • 代码实现:
/*
    练习2:通过配置文件运行类中的方法
 */
public class ReflectTest02 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {


        //加载数据
        Properties prop = new Properties();
        FileReader fr = new FileReader("myReflect\\class.txt");
        prop.load(fr);
        fr.close();

        /*
            className=com.itheima_06.Student
            methodName=study
         */
        String className = prop.getProperty("className"); // com.itheima_06.Student
        String methodName = prop.getProperty("methodName"); // study

        // System.out.println(className);
        // System.out.println(methodName);

        //通过反射来使用
        Class<?> c = Class.forName(className);//com.itheima_06.Student

        Object obj = c.newInstance();
      /*  Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();*/

        Method m = c.getDeclaredMethod(methodName);//study
        // 取消访问检查
        m.setAccessible(true);
        // 执行方法
        m.invoke(obj);
    }
}

3.模块化

3.1 模块化概述【理解】

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

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

3.2 模块的基本使用【应用】

  1. 在项目中创建两个模块。一个是myOne,一个是myTwo
  2. 在myOne模块中创建以下包和以下类,并在类中添加方法
  3. 在myTwo模块中创建以下包和以下类,并在类中创建对象并使用
  4. 在myOne模块中src目录下,创建module-info.java,并写入以下内容
    • exports cn.itcast;
  5. 在myTwo模块中src目录下,创建module-info.java,并写入以下内容
    • requires myOne;

3.3 模块服务的基本使用【应用】

  1. 在myOne模块中新建一个包,提供一个接口和两个实现类

  2. 在myOne模块中修改 module-info.java文件,添加以下内容

    • exports com.itheima_03;
    • provides MyService with Czxy;
  3. 在myTwo模块中新建一个测试类
    //加载服务
    ServiceLoader myServices = ServiceLoader.load(MyService.class);

    //遍历服务
    for(MyService my : myServices) {
    my.service();
    }

  4. 在myTwo模块中修改 module-info.java文件,添加以下内容

    • uses MyService;

反射使用到的Student类


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;
    }

    // 方法是私有的而且参数String s, int i 带返回值的
    private String method4(String s, int i){
        return s + ":" + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + 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;
    }

    // 方法是私有的而且参数String s, int i 带返回值的
    private String method4(String s, int i){
        return s + ":" + i;
    }

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

相关标签: 反射