包里替换class文件_Java 反射之根基 Class 类
Java 反射之根基 Class 类
Java中反射机制很重要,Java的动态语言就是靠反射机制实现的,反射技术也是程序员走的更远必不可少的一个技能。一般情况下我们都是通过类来创建对象,如果要求通过一个对象找到一个类,就需要用到反射机制,各种开源框架的编写更是离不开反射的机制。
一、了解反射机制
一般我们写代码,按照如下的步骤使用一个类:
1、使用关键字 import 导入类所在的包;
2、使用类名称或者接口名称定义对象;
3、通过关键字 new 进行类对象实例化;
4、使用【对象.属性】进行类中属性的调用;
5、使用【对象.方法】进行类中方法的调用;
而 Java 中的反射过程就是指:在程序的运行过程中,把 Java 类中的各种元素映射成对应的类,并能动态的执行这些类的方法。
Java 反射机制里重要的几个类:
类:java.lang.Class
属性:java.lang.reflect.Field
构造方法:java.lang.reflect.Constructor
方法:java.lang.reflect.Method
用反射可以轻松的获取一个类中的以上元素,并可以动态地对其进行调用,在不知道别人写的代码的时候,可以通过配置来调用别人的代码,很多开源框架都离不开反射机制,反射的魅力也正如此。
二、认识 Class 类
1、了解 Object 类:
我们知道如果一个类没有明确的声明集成自哪个父类时,那么它默认继承 Object 类,Object 类是所有类的父类。
Object 类中的 getClass()方法的源码:
public final native Class<?> getClass();
getClass()方法返回的类型是一个 Class 类,Class 类就是 Java 反射的源头。以上的源码用到了 native 关键字和泛型,使用 native 关键字说明这个方法是原生函数,也就是这个方法是用 C/C++ 语言实现的,由 Java 通过 JNI 去调用的本地接口;如果不让程序出现警告信息,可以在使用时指定其操作的泛型具体类型,或者直接用“?”来取代。
2、获取 Class 类的 4 种实例化方式:
1、通过类本身的 class 属性实例化【类.class】;
2、通过 Object 类的 getClass()方法实例化【对象.getClass()】;
3、通过【Class.forName()方法】实例化,这种方式最常用,体现出了反射的动态性;
4、通过类的加载器获取;
```java /* * 如何获取Class类的实例的4种方式 / @Test public void TestClass() throws Exception { // 1、调用运行时类本身的.class属性 Class<?> clazz = User.class; System.out.println(clazz);
// 2、通过运行时类的对象获取
User p = new User();
Class<?> clazz1 = p.getClass();
System.out.println(clazz1);// 3、通过Class的静态方法获取,体现了反射的动态性,
// 传入className就能创建Class类的实例
String className = "com.jpm.reflection.User";
Class<?> clazz3 = Class.forName(className);
System.out.println(clazz3);// 4、通过类的加载器获取
ClassLoader classLoader = this.getClass().getClassLoader();
Class clazz4 = classLoader.loadClass(className);
System.out.println(clazz4);
}
/* * User类,用于演示反射,为了不影响体验,代码见文章末尾 / ```
运行结果:
class com.jpm.reflection.User
class com.jpm.reflection.User
class com.jpm.reflection.User
class com.jpm.reflection.User
三、类的加载器 ClassLoader
1、了解 Class 类的 3 种加载器:
1、系统类加载器(AppClassLoader):加载自定义类和普通 jar 包;
2、扩展类加载器(ExtClassLoader):加载 jre/lib/ext 目录下的类;
3、启动类加载器(BootStrapClassLoader):加载 jdk 的核心类库,启动类加载器 Java 代码获取不到;
/*** 类的加载器测试*/@Testpublic void testClassLoader() throws Exception {ClassLoader loader1 = this.getClass().getClassLoader();// 获取系统类加载器:sun.misc.Launcher$AppClassLoader@7852e922System.out.println(loader1);ClassLoader loader2 = loader1.getParent();// 获取系统类加载器的父类,扩展类加载器:sun.misc.Launcher$ExtClassLoader@330bedb4System.out.println(loader2);ClassLoader loader3 = loader2.getParent();// 获取扩展类的加载器的父类为null,说明引导类加载器无法在代码中获取System.out.println(loader3);Class clazz1 = User.class;ClassLoader loader4 = clazz1.getClassLoader();// 普通类用系统类加载器加载:sun.misc.Launcher$AppClassLoader@7852e922System.out.println(loader4);Class clazz2 = Class.forName("java.lang.String");ClassLoader loader5 = clazz2.getClassLoader();// String类是jdk的核心类库,用引导类加载器加载,返回null,说明类加载器无法在代码中获取System.out.println(loader5);}
运行结果:
sun.misc.Launcher$AppClassLoader@7852e922
sun.misc.Launcher$ExtClassLoader@330bedb4
null
sun.misc.Launcher$AppClassLoader@7852e922
null
2、类加载器的应用案例
1、获取 Java 包里的配置文件
@Testpublic void test() throws IOException {// 类加载器的应用,获取java包里的配置文件,但是不能获取工程目录下的文件ClassLoader loader = this.getClass().getClassLoader();InputStream is = loader.getResourceAsStream("configs//jdbc.properties");Properties properties = new Properties();properties.load(is);is.close();String user = properties.getProperty("user");System.out.println(user);String pwd = properties.getProperty("pwd");System.out.println(pwd);// 文件名不一定是properties后缀,也可以是txt等InputStream is1 = loader.getResourceAsStream("configs//jdbc.txt");Properties properties1 = new Properties();properties1.load(is1);is1.close();String user1 = properties1.getProperty("user");System.out.println(user1);String pwd1 = properties1.getProperty("pwd");System.out.println(pwd1);}
配置文件内容:
运行结果:
properties
jdbc.properties
txt
jdbc.txt
2、获取工程下的配置文件
上面的类加载器获取 java 包里的配置文件,但是不能获取工程目录下的文件,要想获取工程目录下的文件,可以使用如下的代码:
@Testpublic void test2() throws IOException {// 工程下的文件获取,文件名不一定是properties后缀,也可以是txt等InputStream is = new BufferedInputStream(new FileInputStream(new File("jdbc2.properties")));Properties pro = new Properties();pro.load(is);is.close();System.out.println(pro.getProperty("user"));System.out.println(pro.getProperty("pwd"));}
运行结果:
root
root123
四、Java 反射初体验
下面一个例子用来演示如何通过 Java 的反射机制,动态创建 User 类对象,并调用 User 类对象的属性赋值以及调用它的方法。
/*** 反射的初步体验*/@Testpublic void TestReflection() throws Exception {Class<?> clazz = Class.forName("com.jpm.reflection.User");// 创建运行时类User的对象Object user = clazz.newInstance();System.out.println(user);// 通过反射调用运行时类的指定public属性Field f1 = clazz.getField("name");f1.set(user, "JPM");System.out.println(user);// 通过反射调用运行时类的指定private属性Field f2 = clazz.getDeclaredField("age");f2.setAccessible(true); // 为私有属性赋值f2.set(user, 18);System.out.println(user);// 通过反射调用运行时类的指定方法Method m1 = clazz.getMethod("show");m1.invoke(user);Method m2 = clazz.getMethod("display", String.class);m2.invoke(user, "BJ");}/*** User类,用于演示反射*/
public class User {public String name;private int age;// 创建类时尽量写一个空参的构造器public User() {super();}public User(String name) {super();this.name = name;}public User(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + "]";}public void show() {System.out.println("show method run!");}public void display(String address) {System.out.println("display method run,address=" + address);}
}
运行结果:
User [name=null, age=0]
User [name=JPM, age=0]
User [name=JPM, age=18]
show method run!
display method run,address=BJ
本文主要介绍了反射的概念、反射的源头 Class 类、类的 3 种加载器、类加载器ClassLoader 的应用场景、用Java 反射获取用户自定义类User,初步体验了 Java 反射机制的魅力。
后面我会用 2 篇文章来说明 Java 反射机制的深入体验,反射的高级应用动态代理的实现,敬请期待......
包里替换class文件_Java 反射之根基 Class 类相关推荐
- 提取原rpm包里的SPEC文件及重新打包
一.概要 目的是要修改原rsyslog rpm包的systemd rsyslog.service文件,添加一行"ExecStartPre=/bin/bash -c "/usr/bi ...
- java 类.class_Java 反射之根基 Class 类
Java 反射之根基 Class 类 Java中反射机制很重要,Java的动态语言就是靠反射机制实现的,反射技术也是程序员走的更远必不可少的一个技能.一般情况下我们都是通过类来创建对象,如果要求通过一 ...
- java反射class文件_Java反射(一)Class
Java的反射应该算Java最灵活的一部分,反射机制是站在更高层次的抽象上,把Java中的类.方法.构造器.成员变量.接口等又抽象成了一个个类.先说说反射的基石Class类吧. Class类的实例表示 ...
- 在服务器里替换class文件,tomcat项目中class文件替换无效引发的思考
最近在项目部署需要修改补丁文件时,我发现了一个特别古怪的问题: 替换掉原先的class文件无效,重启服务器也无效! 一般来说,我们更新网站,就是把更新后的文件,如jsp.class文件,替换掉原先的c ...
- java 反射类成员_java 反射(二)类成员
在Java反射的包中定义一个接口java.lang.reflect.Member,它有三个实现类java.lang.reflect.Field, java.lang.reflect.Method, a ...
- javabean反射改字段内容_java反射机制给实体类相同字段自动赋值实例
一.封装一个工具类 1.简易版 package net.aexit.construct.acceptance.websky.utils; import java.lang.reflect.Field; ...
- 怎么导出ij里面的java文件_Java應用系列:命令行生成jar包(附IJ Idea導出jar方法)...
jar包 JAR(Java Archive,Java 歸檔文件)是與平台無關的壓縮文件,通常是用於將多個class文件組合成一個,.當創建jar包的時候,如果程序中有main入口函數,同時manife ...
- java.lang.class对象_Java反射——java.lang.Class 类简介
Java的基本思想之一是万事万物即对象,类也是一种对象.但是类是什么对象呢?Java中的类是java.lang.Class的实例化对象,这被成为类类型. //java.lang.Class类中的的主要 ...
- java class 使用_Java反射机制(Class类的使用)
1:通过无参构造实例化对象 package cn.itcast; /* * 通过无参构造实例化对象 * 通过Class类本身实例化对象,使用newInstance方法 * 需要注意的是:实例化类中存在 ...
最新文章
- Java 动态绑定 静态绑定
- redis常用命令getex_Redis常用命令(key、string、List)
- BufferedReader和FileReader的区别
- Linux bashrc和profile的用途和区别
- error: expected expression before ‘;’ token的问题
- 【报告分享】2021H1电商发展分析报告.pdf(附下载链接)
- 监控zabbix 服务并在异常时python 邮件报警
- cnBlog的windows live writer 客户端配置
- 企业微信2.6.0发布 可与微信用户群聊了
- Windows NT 5.1,Windows NT 6.0,Windows NT 6.1的概念
- SAP PP 空bom 清单及处理
- 使用vite插件编写tsx文件
- 做外贸找国外采购商的七个新方法
- 数据中心UPS不间断电源系统架构介绍
- 使用Visual Studio IDE编写程序时不显示窗口或窗口一闪而逝的解决方法
- 红米note4出厂系统版本_红米Note4发布!出厂就有MIUI8黑科技
- #730 (Div. 2) A 思维 C dfs D1 交互思维
- pandas.melt()使用介绍(宽表变长表)
- 《程序员修炼之道》读书笔记(二)--第三周
- 每天3.2亿人在刷抖音,而那些优秀的人却看这公众号的精华文章!