暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java反射机制(三)

遇见0和1 2020-04-03
463



01
类加载器

类加载器的作用:


类加载的作用:将 class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些 Class对象。


类加载器作用是用来把类(class)装载进内存的。



示例代码





Java

package com.lingstudy.reflection;


public class Test07 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2


//获取系统类加载器的父类加载器-->扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);//sun.misc.Launcher$ExtClassLoader@1540e19d


//获取扩张类加载器的父类加载器-->根加载器(c/c++)
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);//null 无法直接获取


//测试当前类是哪个加载器加载的
ClassLoader classLoader = Class.forName("com.mjane.reflection.Test07").getClassLoader();
System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@18b4aac2


//测试JDK内置的类是哪个加载器加载的
classLoader = Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);//null 根加载器加载的


//如何获得系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
/*
E:\JAVA\jdk-8u131-windows-x64_8.0.1310.11\jre\lib\charsets.jar;
E:\JAVA\jdk-8u131-windows-x64_8.0.1310.11\jre\lib\deploy.jar;
E:\JAVA\jdk-8u131-windows-x64_8.0.1310.11\jre\lib\ext\access-bridge-64.jar;
D:\IDEA\projects\AnnotationStudy\out\production\AnnotationStudy;
D:\IDEA\IntelliJ IDEA 2019.2.3\lib\idea_rt.jar
.........
..........
*/


}
}


02
获取类的运行时结构

通过反射获取运行时类的完整结构

Field、Method、Constructor、Superclass、Interface、Annotation

  • 实现全部接口

  • 所继承的父类

  • 全部的构造器

  • 全部的方法

  • 全部的Field

  • 注解


示例代码





Java

package com.lingstudy.reflection;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


//获得类的信息
public class Test08 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.mjane.reflection.User");


//获得类的名字
System.out.println(c1.getName());//获得User类的包名 + 类名
System.out.println(c1.getSimpleName());//获得User类的类名


//获得类的属性
Field[] fields = c1.getFields();//只能找到public属性
// for (Field field : fields) {
// System.out.println(field);
// }
fields = c1.getDeclaredFields();//可以找到全部的属性
for (Field field : fields) {
System.out.println(field);
}


//获得指定属性的值
Field name = c1.getDeclaredField("name");
System.out.println(name);


//获得类的方法
System.out.println("==================");
Method[] methods = c1.getMethods();//获得父类及本类的所有public方法
for (Method method : methods) {
System.out.println("正常的:" + method);
}
methods = c1.getDeclaredMethods();//获得本类的所有方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==================");
//获得指定的方法
//重载
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);


System.out.println("==================");
//获得指定构造器
Constructor[] constructors = c1.getConstructors();//获得public
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
constructors = c1.getDeclaredConstructors();//获得全部的
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//获得指定的构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
System.out.println("指定的构造器:"+declaredConstructor);


}
}



03
动态创建对象执行方法

小结:
  • 在实际的操作中,取得类的信息的操作代码,并不会经常开发。

  • 一定要熟悉java.lang.reflect包的作用,反射机制。

  • 如何取得属性、方法、构造器的名称,修饰符等。

有了Class对象能做什么?

创建类的对象:调用 Class对象的newlnstance()方法

    1)类必须有一个无参数的构造器。

    2)类的构造器的访问权限需要足够。

思考?难道没有无参的构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。

步骤如下:

    1)通过Class类的getDeclaredConstructor(Class... parameterTypes)取得本类的指定形参类型的构造器

        2)向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。

        3)通过Constructor实例化对象。


示例代码





Java

package com.lingstudy.reflection;


import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


//动态的创建对象,通过反射
public class Test09 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获得Class对象
Class c1 = Class.forName("com.mjane.reflection.User");


//构造一个对象
//User user = (User) c1.newInstance();//本质上是调用了类的无参构造器
//System.out.println(user);//User{name='null', id=0, age=0}


//通过构造器创建对象
//1.获得构造器(User类的有参构造器)
//Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
//2.使用构造器创建一个象
//User user2 = (User) constructor.newInstance("与世间美好环环相扣", 001, 18);
//System.out.println(user2);//User{name='与世间美好环环相扣', id=1, age=18}


//通过反射调用普通方法
User user3 = (User) c1.newInstance();
//通过反射获取一个方法
Method setName = c1.getDeclaredMethod("setName", String.class);
//invoke :激活
// (对象,"方法的值")
setName.invoke(user3,"略简");
System.out.println(user3.getName());//略简


System.out.println("======================");
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field name = c1.getDeclaredField("name");//获取name属性


//不能直接操作私有属性,需要关闭程序的安全监测,属性或方法的setAccessible(true);
name.setAccessible(true);//设置权限:可以访问
name.set(user4,"略简2");
System.out.println(user4.getName());//略简2


}
}


04
反射操作注解

  • getAnnotations

  • getAnnotation


了解什么是ORM?
Object relationship Mapping-->对象关系映射
1)和表结构对应
2)属性和字段对应
3)对象和记录对应
  • 要求:利用注解和反射完成类和表结构的映射关系


id
name
age
001
编程之外
3
002
lingStudy
18



示例代码





Java

package com.lingstudy.reflection;


import java.lang.annotation.*;
import java.lang.reflect.Field;


//反射操作注解
public class Test12 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.mjane.reflection.Student2");


//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);//@com.mjane.reflection.TableJane(value=db_student)
}


//获得注解的value的值
TableJane tableJane = (TableJane) c1.getAnnotation(TableJane.class);
String value = tableJane.value();
System.out.println(value);//db_student

//获得类指定的注解
Field f = c1.getDeclaredField("name");
FieldJame annotation = f.getAnnotation(FieldJame.class);
System.out.println(annotation.columnName());//db_name
System.out.println(annotation.type());//varchar
System.out.println(annotation.length());//3


}
}


//实体类
@TableJane("db_student")
class Student2{


@FieldJame(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldJame(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldJame(columnName = "db_name",type = "varchar",length = 3)
private String name;


public Student2() {
}


public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}


public int getId() {
return id;
}


public void setId(int id) {
this.id = id;
}


public int getAge() {
return age;
}


public void setAge(int age) {
this.age = age;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


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


//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableJane{
String value();
}


//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldJame{
String columnName();
String type();
int length();
}
05
编程之外

好好学习,认真总结,加油



CSDN:与世间美好环环相扣

公众号:编程之外
扫码关注编程之外
文章转载自遇见0和1,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论