1.类加载器:
概述:是负责将磁盘上的某个class文件读取到内存并生成Class对象
如何获取类加载器:
类的字节码对象.getClassLoader()
2.Java中有三种类加载器,它们分别用于加载不同种类的class
- 启动类加载器:用于加载系统类库 <java_home>\bin目录下的class,比如 .jar
- 扩展类加载器:用于加载扩展类库 <java_home>\lib\ext目录下的class
- 应用程序加载器:用于加载我们自定义类的加载器
// 获取 Test类的类加载器
ClassLoader c1 = Tests.class.getClassLoader();
System.out.println(c1);// jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
// 获取 Student类的类加载器
ClassLoader c2 = Student.class.getClassLoader();
System.out.println(c2);// jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
// 获取 String类的类加载器
ClassLoader c3 = String.class.getClassLoader();
System.out.println(c3);// null
/*
* API中说明:一些实现可能使用null来表示引导类加载器。
* 如果此类由引导类加载器加载,则此方法将在此类实现中返回null
* */
System.out.println("=====================委派机制============");
System.out.println(c1.getParent());// jdk.internal.loader.ClassLoaders$PlatformClassLoader@6e8dacdf
//System.out.println(c3.getParent());// java.lang.NullPointerException
System.out.println(c1.getParent().getParent());// null,最高层
3.Class对象的获取方式
IDEA 工具中的对象是怎么知道类有哪些属性和哪些方法的?
- 通过反射技术对 对象进行了解剖,获取了类的所有成员属性和方法
反射的概念
- 反射是一种机制,利用该机制可以在程序运行的过程中对类进行解剖 并操作类中的所有成员变量、方法以及构造
使用反射操作类成员的前提
- 要获得该类字节码文件对象,就是Class对象
反射在实际开发中引用
- IDEA工具,Eclipse工具等代码开发工具都是反射机制,能够知道类.之后该类中的所有成员
- 后期要学习的各种框架
总结:
通过反射技术去获取一个类的成员变量,方法,构造方法等,并可以访问
因此,我们要了解反射机制,使用反射,就需要获取Class对象,这是使用反射操作的前提
获取Class的方式:
1.通过类名.getClass
2.通过对象名称.getClass()
3.通过Class的静态方法获得:public static Class<?> forName(String className)
注意:每一个类的Class对象都只有一个
public class Tests {
public static void main(String[] args) throws ClassNotFoundException {
// 通过类名称.class
Class<Student> c1 = Student.class;
//通过对象名称.getClass()
Student s = new Student();
Class<? extends Student> c2 = s.getClass();
// 通过Class静态方法获得
Class<?> c3 = Class.forName("com.donglan.demo07_Class对象的获取方式.Student");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}
}
public class Student {
public String name;
}
4.Class类的常用方法
String getSimpleName():获得类的名字字符串:类名
String getName():获得类全名:包名+类名
T newInstance():创建Class对象关联类的对象
public class Tests {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
// 获得Student类的Class对象
Class<Student> c = Student.class;
// 获得类名字符串
String name = c.getSimpleName();
System.out.println(name);// Student
// 获得类全名
String name1 = c.getName();
System.out.println(name1);// com.donglan.demo07_Class对象的获取方式.Student
// 创建Student对象
Student student = c.newInstance();// 其实就相当于调用了Student类中的无参构造方法
System.out.println(student);// 7a79be86
}
}
5.反射之操作构造方法
Java中一切皆对象,该类中的每一个构造方法都属于一个对象,那么我们在定义Student s的时候,通过对向赋值的方式给S赋值
Student s = new Student();
其实我们把 public Student(){}无参构造方法看作一个对象
Student s = 对象1(public Student(){})
public class Student {
public String name;
public int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name) {
this.name = name;
}
private Student(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Constructor概述
类中的每一个构造方法都是一个Constructor类的对象
反射之操作构造方法的目的
获得Constructor对象来创建类的对象
使用:
1.如何通过反射获取一个类的构造方法:Class类的方法
- public Constructor<T> getConstructor(Class<?>... parameterTypes)
根据参数类型获得对应的Constructor对象
只能获得public修饰的构造方法
- public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
根据参数类型获得对应的Constructor对象
可以是public、protected、默认、private修饰符修饰的构造方法
- public Constructor<?>[] getConstructors()
获得类中的所有构造方法,只能获取public修饰的
- public Constructor<?>[] getDeclaredConstructors()
获得类中所有的构造方法
可以是public、protected、默认、private修饰符修饰的构造方法
2.如何通过反射执行获取的构造方法:Constructor的方法
- public T newInstance(Object ... initargs)
根据指定的参数创建对象
- public void setAccessible(boolean flag)
设置“暴力反射” : 是否取消权限检查,true是取消权限检查,false是不取消
public class Tests {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获得Student的Class对象
Class<Student> c = Student.class;
// 获取单个构造方法
// 获取无参构造方法
Constructor<Student> constructor1 = c.getDeclaredConstructor();
System.out.println(constructor1);
// 获取满参构造方法
Constructor<Student> constructor2 = c.getDeclaredConstructor(String.class,int.class);
System.out.println(constructor2);
// 获取单参的构造方法
Constructor<Student> constructor3 = c.getDeclaredConstructor(String.class);
System.out.println(constructor3);
Constructor<Student> constructor4 = c.getDeclaredConstructor(int.class);
System.out.println(constructor4);
System.out.println("============================================");
// 获取所有构造方法
Constructor<?>[] constructors = c.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("============================================");
// 通过执行 constructor1 表示的构造方法来创建Student对象
Student s1 = constructor1.newInstance();
System.out.println(s1);
// 通过执行 constructor2 表示的构造方法来创建Student对象
Student s2 = constructor2.newInstance("张三",18);
System.out.println(s2);
// 通过执行 constructor3 表示的构造方法来创建Student对象
// 取消constructor3表示的构造方法的权限检查
constructor4.setAccessible(true);
Student s4 = constructor4.newInstance(18);
System.out.println(s4);
}
}