Java SE:反射超详解(二)

简介: Java SE:反射超详解(二)

5.3 获取某个类的类加载器对象

通过这个类的CLass对象.getCLassLoader()

代码演示如下:

public class TestMain {
    public static void main(String[] args) throws ClassNotFoundException {
        //引导区的类加载器
        Class c1= Class.forName("java.lang.String");
        ClassLoader classLoader = c1.getClassLoader();
        System.out.println("Str类的类加载器:"+classLoader);//Str类的类加载器:null
        //why?引导区的类加载器不是由Java语言实现的,所以得不到它的对象,故而为null
        //应用程序类加载器
        Class c2= Class.forName("exercise.e10.TestMain");
        ClassLoader loader = c2.getClassLoader();
        System.out.println(loader);//sun.misc.Launcher$AppClassLoader@18b4aac2 应用程序类加载器
        //扩展类加载器
        Class c3=Class.forName("sun.security.pkcs11.Config");
        System.out.println(c3.getClassLoader());//sun.misc.Launcher$ExtClassLoader@54bedef2
    }
}


六. 反射的基本应用

🤮注意:

特别用cLass.forName(“类型的全名称”)获取class对象时

若被打jar包的模块中发生代码的增删修改,比如新建一个类或成员变量或方法。一定要及时build Artifacts–>build 自己打好的jar包,然后把新build的jar包及时替换到jdk–>jre–>lib-ext目录下

6.1 获取类型的详细信息

🚩只要可以获取一个类的CLass对象,就可以获取它里面的所有的信息。

代码演示如下:

@Test
    public void test01() throws ClassNotFoundException {
        Class c1=Class.forName("java.lang.String");
        //1)获取String类的class对象的包名
        System.out.println(c1.getPackage());
        //2)获取class对象的类名
        System.out.println(c1.getName());
        //3)获取类的修饰符
        int modifiers = c1.getModifiers();
        System.out.println(modifiers);//17
        System.out.println(Modifier.toString(modifiers));
        //4)获取类的父类
        System.out.println(c1.getSuperclass());
        //5)获取类的实现的接口
        System.out.println(c1.getName()+"实现的接口:");
        Class[] interfaces = c1.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println(anInterface);
        }
        //6)获取String类的成员变量
        /*
        获取string类所有成员变量
        clazz.getField("属性名");   获取某一个公共的成员变量
        clazz.getFields();          获取所有的公共的成员变量
        clazz.getDeclaredField("属性名"); 获取某一个已声明的成员变量
        clazz.getDeclaredFields();   获取所有已声明的成员变量,包括非公共的,私有的等
*/
        System.out.println("String类的所有成员变量:");
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //7)获取String类的构造方法
        //获取string类的构造器们
/*      clazz.getConstructor(构造器的形参类型列表)  获取一个公共的构造器
        clazz.getConstructors(); 获取所有公共的构造器
        clazz.getDeclaredConstructor(构造器的形参类型列表) 获取一个已声明的构造器
        clazz.getDeclaredConstructors();  获取所有已声明的构造器
        */
        System.out.println(c1.getName()+"所有的构造器:");
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //8)获取String类的方法们
        //获取string类的方法们
        /*
        cLazz.getMethod(方法名, 方法的形参类型列表): 获取某个公共的方法
        clazz.getDeclaredMethod(方法名,方法的形参类型列表): 获取某个已声明的方法
        clazz.getMethods() 获取所有公共的方法
        clazz.getDeclaredMethods() 获取所有已声明的方法 */
        System.out.println(c1.getName()+"所有的方法们:");
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("-------------------------------------------");
        Class c2= ArrayList.class;
        //9)获取ArrayList的子类们
        System.out.println(c2.getName()+"所有的内部类们:");
        Class[] declaredClasses = c2.getDeclaredClasses();
        for (Class innerClass : declaredClasses) {
            System.out.println(innerClass);
        }
    }

6.2 创建任意类型的对象

🚩当然不包括 基本数据类型和void,抽象类,接口等

6.2.1 方案一

步骤:

(1) 先获取这个类的CLass对象

(2) 调用CLass对象的newInstance()方法来创建实例对象

🔔注意:

这种方式创建对象有限制,必须要求这个类有无参的公共构造器

代码演示如下:

@Test
public void test02() throws Exception {
    Class<?> c1 = Class.forName("testPackage.TestMain");
    Object obj = c1.newInstance();
    System.out.println(obj);//java.lang.ClassNotFoundException: testPackage.TestMain
    //原因:另一个模块outerModule的testPackage.TestMain没有导入到本模块demo的train.t1 的扩展类加载器中
}

🚩如何导出为jar包?

请看如下演示:

1)单击工具栏的图标,如下所示:

然后打开项目设置

2)选择Artifacts(打包部署),选择添加jar。

3)给导出的jar命名,确认导出的路径

4)确认创建或选择已有的Manifest.MF文件。单词“manifest”的意思是“显示” 。 这个 manifest 文件定义了与扩展和包相关的数据。

🌏 说明:

打开Java的JAR文件,我们经常可以看到文件中包含着一个META-INF目录,这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息 。

5)选择Manifest.MF文件存储目录。

6)选择jar要包含的.class文件的目录,即要打包的模块的out目录

7)编译生成jar

💡小tips:

编译好的jar包在哪里?

在第三步中创建jar包时指定的jar包存储路径里去找

8)把编译好的jar包复制,粘贴到jdk安装目录下 jre–>lib–>ext 下

💡小tips:

这样就可以通过扩展类加载器去找另一个模块下的类的clss对象

代码演示如下:

public class t1 {
    public static void main(String[] args) throws Exception{
        Class<?> c1 = Class.forName("testP1.testMain");
        Object obj = c1.newInstance();//这个obj对象实际上是模块Testmodule下的testP1.testMain类的对象
        System.out.println(obj);
    }
}

代码演示如下:

Class c2=Class.forName("testP1.testDemo");
Object o = c2.newInstance();//这个obj对象实际上是模块Testmodule下的testP1.testDemo类的对象
System.out.println(o);
/*
Exception in thread "main" java.lang.InstantiationException: testP1.testDemo
Caused by: java.lang.NoSuchMethodException: testP1.testDemo.<init>()
模块Testmodule下的testP1.testDemo类没有无参构造
*/

相关文章
|
5月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
947 1
|
8月前
|
设计模式 算法 Java
Java SE 与 Java EE 组件封装使用方法及实践指南
本指南详细介绍了Java SE与Java EE的核心技术使用方法及组件封装策略。涵盖集合框架、文件操作、Servlet、JPA、EJB和RESTful API的使用示例,提供通用工具类与基础组件封装建议,如集合工具类、文件工具类、基础Servlet、实体基类和服务基类等。同时,通过分层架构集成示例展示Servlet、EJB和JPA的协同工作,并总结组件封装的最佳实践,包括单一职责原则、接口抽象、依赖注入、事务管理和异常处理等。适合希望提升代码可维护性和扩展性的开发者参考。
283 0
|
Oracle Java 关系型数据库
Java(TM) Platform SE binary 已停止工作”的解决方法
Java(TM) Platform SE binary 已停止工作”的解决方法
1793 141
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
监控 Java
Java基础——反射
本文介绍了Java反射机制的基本概念和使用方法,包括`Class`类的使用、动态加载类、获取方法和成员变量信息、方法反射操作、以及通过反射了解集合泛型的本质。同时,文章还探讨了动态代理的概念及其应用,通过实例展示了如何利用动态代理实现面向切面编程(AOP),例如为方法执行添加性能监控。
184 5
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
284 9
Java——反射&枚举
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
Java
Java的反射
Java的反射。
160 2
|
安全 Java 测试技术
🌟Java零基础-反射:从入门到精通
【10月更文挑战第4天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
233 2
|
IDE Java 编译器
java的反射与注解
java的反射与注解
134 0