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类没有无参构造 */