定义一个实体类
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
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;
}
public String toString() {
return "Person{name = " + name + ", age = " + age + "}";
}
}
获取当前创建类的实力对象
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.huaijiuwang.test.Person");
System.out.println(c1);
}
创建多个看看是否是同一个对象
Class c1 = Class.forName("com.huaijiuwang.test.Person");
Class c2 = Class.forName("com.huaijiuwang.test.Person");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
值相等:说明创建出来的实力都是同一个(一个类在内存中只有一个Class对象)
// 方式1
Class c1 = Class.forName("com.huaijiuwang.test.Person");
// 方式2
Person person = new Person();
Class c2 = person.getClass();
// 方式三
Class c3 = Person.class;
输出看结果
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
这几种方式获取的都是同一个类的对象
Class<Integer> c4 = Integer.TYPE; // 获取系统数据类型(包装类)
System.out.println(c4);
public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); // 里面自己写的TYPE类型
Class c1 = Person.class;
Class c2 = c1.getSuperclass();
System.out.println(c1);
System.out.println(c2);
Class c1 = Object.class; // 类
Class c2 = Comparable.class; // 接口
Class c3 = String[].class; // 一维数组
Class c4 = String[][].class; // 二维数组
Class c5 = Override.class; // 注解
Class c6 = ElementType.class; // 枚举类型
Class c7 = Integer.class; // 基本数据类型
Class c8 = void.class; // void
Class c9 = Class.class; // Class 本身
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
比较两个数组之间的对象区别
一维数组和一维数组间:
String[] s1 = new String[10];
String[] s2 = new String[100];
System.out.println(s1.getClass().hashCode());
System.out.println(s2.getClass().hashCode());
一维数组和二维数组间:
String[] s1 = new String[10];
String[][] s2 = new String[100][];
System.out.println(s1.getClass().hashCode());
System.out.println(s2.getClass().hashCode());
结论:
数据的对象是根据维度来区分是否是同一个Class对象的。(只要元素类型和维度一样就是同一个Class)
执行代码看效果:
public class Test2{
public static void main(String[] args) throws ClassNotFoundException {
A a = new A();
}
}
class A{
static {
a = 200;
}
static int a = 100;
public A(){
System.out.println(a);
}
}
class A{
static int a = 100;
static {
a = 200;
}
public A(){
System.out.println(a);
}
}
结论:
在执行
a = 100;
a = 200;
}
执行逻辑就是被static修饰的代码会在加载类初始化阶段进行执行,执行逻辑是从上到下,谁的代码在后,最后就是运行的结果,
这边是先给a赋值为100,然后在覆盖赋值为200,所有执行的结果就是200.
测试:
创建类
class A{
static int a = 100;
static {
System.out.println("父类初始化");
}
}
class B extends A{
static int b = 100;
static final int M = 200;
static {
System.out.println("子类初始化");
}
}
public class Test2{
static {
System.out.println("Main 加载初始化");
}
public static void main(String[] args) throws ClassNotFoundException {
// 会触发类的加载
}
}
public static void main(String[] args) throws ClassNotFoundException {
// 会触发类的加载
new B(); // 主动引用
}
Class.forName("com.huaijiuwang.test.B"); // 通过反射
System.out.println(B.b); // 引用子类常量
// 不会输出类的加载的方式
System.out.println(B.a); // 掉用父类的静态属性
B[] bs = new B[10]; // 创建对象数组
System.out.println(B.M); // 访问常量
测试:
public static void main(String[] args){
// 获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// 获取系统类加载器的父加载器--->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
// 获取扩展类加载器的父加载器--->根加载器
ClassLoader parent1 = parent.getParent();
// 输出
System.out.println(systemClassLoader); // sun.misc.Launcher$AppClassLoader@14dad5dc
System.out.println(parent); // sun.misc.Launcher$ExtClassLoader@2503dbd3
System.out.println(parent1); // null
}
测试当前运行的类是那个加载器加载的
Class c1 = Class.forName("com.huaijiuwang.test.Test2");
ClassLoader classLoader = c1.getClassLoader();
System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@14dad5dc
默认是系统类加载器(应用类加载器)
测试系统类的加载器是谁:
c1 = Class.forName("java.lang.Object");
ClassLoader classLoader1 = c1.getClassLoader();
System.out.println(classLoader1); // null
// 获取系统类加载器的路径
System.out.println(System.getProperty("java.class.path"));
/*
C:\Program Files\Java\jdk1.8.0_40\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\deploy.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\access-bridge-64.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\cldrdata.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\dnsns.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\jaccess.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\jfxrt.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\localedata.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\nashorn.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\sunec.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\sunjce_provider.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\sunmscapi.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\sunpkcs11.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\ext\zipfs.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\javaws.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\jce.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\jfr.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\jfxswt.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\jsse.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\management-agent.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\plugin.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_40\jre\lib\rt.jar;
D:\Idea\Test11\target\classes;
C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpclient\4.5.13\httpclient-4.5.13.jar;
C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore\4.4.13\httpcore-4.4.13.jar;
C:\Users\Administrator\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;
C:\Users\Administrator\.m2\repository\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;
C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpmime\4.5.13\httpmime-4.5.13.jar;
C:\Users\Administrator\.m2\repository\org\jsoup\jsoup\1.12.1\jsoup-1.12.1.jar;D:\办公软件\IntelliJ IDEA 2021.2\lib\idea_rt.jar
*/
代码测试-通过反射获取对象和属性方法
获取类名:
Class c1 = Class.forName("com.huaijiuwang.test.Person");
// 获取类的名字
System.out.println(c1.getName()); // com.huaijiuwang.test.Person 获取类名: 包名 + 类名
System.out.println(c1.getSimpleName()); // Person 获取类名
获取类的属性
Class c1 = Class.forName("com.huaijiuwang.test.Person");
// 获取所有属性
Field[] fields = c1.getFields(); // 只能回去公开属性
for (Field field : fields) {
System.out.println(field);
}
System.out.println("---------------");
fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
// 获取单个属性
System.out.println(c1.getField("name"));
System.out.println(c1.getField("age"));
报错原因:getField方法自能获取public修饰属性
修改代码
System.out.println(c1.getField("name"));
System.out.println(c1.getDeclaredField("age"));
获得类的方法
在Person中添加private方法用于测试
private void test(){}
Class c1 = Class.forName("com.huaijiuwang.test.Person");
// 获取类的方法(可以同时可以直接拿到父类的方法)
Method[] methods = c1.getMethods(); // 获得本类以及父类的全部public方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("---------------------------------");
methods = c1.getDeclaredMethods(); // 获得本类的所有方法包括private修饰的
for (Method method : methods) {
System.out.println(method);
}
输出结果:
public java.lang.String com.huaijiuwang.test.Person.toString()
public java.lang.String com.huaijiuwang.test.Person.getName()
public void com.huaijiuwang.test.Person.setName(java.lang.String)
public int com.huaijiuwang.test.Person.getAge()
public void com.huaijiuwang.test.Person.setAge(int)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
---------------------------------
public java.lang.String com.huaijiuwang.test.Person.toString()
public java.lang.String com.huaijiuwang.test.Person.getName()
public void com.huaijiuwang.test.Person.setName(java.lang.String)
private void com.huaijiuwang.test.Person.test()
public int com.huaijiuwang.test.Person.getAge()
public void com.huaijiuwang.test.Person.setAge(int)
// 获得指定方法
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class); // 这里需要参数类型,因为需要通过参数来判断是否为重载方法
System.out.println(getName);
System.out.println(setName);
获取构造器
添加代码(加一个私有构造器用作区分)
protected Person(int age){
this.age = age;
}
// 获取指定的构造器
Constructor[] constructors = c1.getConstructors(); // 获取public构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("---------------------------");
constructors = c1.getDeclaredConstructors(); // 获取所有构造器
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
// 获取指定构造器
Constructor constructor = c1.getConstructor(String.class, int.class); // 还是一样只能获取公开的构造器
System.out.println(constructor);
// 输出内容
public com.huaijiuwang.test.Person(java.lang.String,int)
// 创建实例对象
Person person = (Person)c1.newInstance();
System.out.println(person);
成功创建对象--删除无参构造方法后测试
直接报错了
当没有空参构造方法的时候我们可以通过获得构造器的方式来创建
// 创建实例对象
// 1.获取构造器
Constructor constructor = c1.getConstructor(String.class, int.class);
// 创建实例对象
Person person = (Person)constructor.newInstance("小红", 20);
System.out.println(person);
创建成功
通过反射调用普通方法
// 创建实例对象
// 1.获取构造器
Constructor constructor = c1.getConstructor(String.class, int.class);
// 创建实例对象
Person person = (Person)constructor.newInstance("小红", 20);
// 通过反射先获取方法
Method setName = c1.getMethod("setName", String.class);
Method getName = c1.getMethod("getName");
// 通过 invoke 方法执行方法
setName.invoke(person, "怀旧");
String name = (String)getName.invoke(person);
System.out.println(person);
System.out.println(name);
通过反射掉用私有方法
// 通过反射调用私有方法
Method test = c1.getDeclaredMethod("test");
test.invoke(person);
// 运行报错
Exception in thread "main" java.lang.IllegalAccessException: Class com.huaijiuwang.test.Test2 can not access a member of class com.huaijiuwang.test.Person with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Method.invoke(Method.java:490)
at com.huaijiuwang.test.Test2.main(Test2.java:21)
原因是有一个开关没打开,打开开关后测试
// 通过反射调用私有方法
Method test = c1.getDeclaredMethod("test");
test.setAccessible(true); // 关闭检查
test.invoke(person);
调用成功,同样属性的操作和方法一样
// 通过反射操作属性
Field age = c1.getDeclaredField("age");
age.setAccessible(true); // 因为age是私有属性 同样关闭检测
// 设置值
age.set(person, 15);
// 获取值
int age1 = (int)age.get(person);
// 打印结果
System.out.println(person);
System.out.println(age1);
Person person = new Person("怀旧", 18);
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
person.getName();
}
long endTime = System.currentTimeMillis();
System.out.println("花费时间: " + (endTime - beginTime) + " ms.");
Class c1 = Class.forName("com.huaijiuwang.test.Person");
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
Person person = (Person)constructor.newInstance("怀旧", 18);
Method getName = c1.getDeclaredMethod("getName");
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(person);
}
long endTime = System.currentTimeMillis();
System.out.println("花费时间: " + (endTime - beginTime) + " ms.");
Class c1 = Class.forName("com.huaijiuwang.test.Person");
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class);
Person person = (Person)constructor.newInstance("怀旧", 18);
Method getName = c1.getDeclaredMethod("getName");
getName.setAccessible(true);
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
getName.invoke(person);
}
long endTime = System.currentTimeMillis();
System.out.println("花费时间: " + (endTime - beginTime) + " ms.");
通过上面的测试可以看出来,直接通过对象调用的方式效率会高很多,而反射的方式,相对于关闭检测后,效率也会有所提升。
在代码中要是用反射的情况较多的情况下,就是建议关闭检测,提高效率
创建测试返回方法
public Map<String, Integer> test(Map<String, Integer> map, List<String> list){
return null;
}
Method method = Test2.class.getMethod("test", Map.class, List.class);
// 获取参数的泛型数据
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
System.out.println("--------------------------");
// 获取返回值的泛型参数数据
Type genericReturnType = method.getGenericReturnType();
System.out.println(genericReturnType);
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
创建一个User类,模拟通过实体类,创建数据库表
class User{
private int id;
private String name;
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String tableName(); // 记录表名
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Filed{
String columnName(); // 字段名
String type(); // 字段类型
int len(); // 字段长度
}
@Table(tableName = "db_user")
class User{
@Filed(columnName = "user_id", type = "int", len = 10)
private int id;
@Filed(columnName = "user_name", type = "varchar", len = 3)
private String name;
}
public static void main(String[] args) throws NoSuchMethodException {
// 创建实例
Class c1 = User.class;
// 定义sql
String sql = "create table ";
// 获取注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
// 获取注解的值
Table table = (Table)c1.getAnnotation(Table.class);
System.out.println(table.tableName());
// 拼接表名
sql += table.tableName() + "( ";
// 获取类所有的字段
for (Field field : c1.getDeclaredFields()) {
Filed filed = field.getAnnotation(Filed.class);
System.out.println(filed.columnName());
System.out.println(filed.type());
System.out.println(filed.len());
// 拼接每个字段
sql += filed.columnName() + " " + filed.type() + "( " + filed.len() + " ), ";
}
// 拼接最后的括号
sql = sql.substring(0, sql.length()-2) + ");";
// 执行sql语句
System.out.println("拼接的sql语句:" + sql);
}
评论
登录后才可以进行评论哦!