在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度。现在将跟着视频做的笔记进行整理。本篇博客是整理Java知识点的第三十六篇博客。
本篇博客介绍了Java的类加载和反射。最后有总结,结束Java学习笔记系列。
本系列博客所有Java代码都使用IntelliJ IDEA编译运行,版本为2022.1。所用JDK版本为JDK11。
目录
当程序需要使用某个类时,如果该类还没有被加载到内存中,系统会通过类的加载、类的连接、类的初始化三个步骤对类进行初始化。通常会连续完成这三个步骤,所以有时将这三个步骤统称为类加载或类初始化。
类的加载就是将class文件读入内存,并为之建立一个java.lang.Class对象。任何类被使用时都会为之建立一个java.lang.Class对象。
类的连接首先要检验被加载的类是否有正确的内部结构,是否与其他类协调一致,然后为类的变量分配内存并设置默认初始化值,最后将类的二进制数据中的符号引用替换为直接引用。
类的初始化主要是对类变量进行初始化。
类的初始化步骤:
如果类还没有被加载和连接,则程序先加载并连接该类。
如果该类的直接父类还未被初始化,就先初始化其直接父类。
如果类中有初始化语句,就依次执行初始化语句。
对直接父类的初始化也遵循这些步骤。
类的初始化时机:
创建类的实例。
调用类的类方法。
访问类或者接口的类变量,或为该类变量赋值。
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。
初始化某个类的子类。
直接用java.exe命令运行某个主类。
类加载器负责将class文件加载到内存中,并生成对应的java.lang.Class对象。
类加载机制有全盘负责,父类委托和缓存机制。
全盘负责:一个类加载器负责加载某个Class时,该Class依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器载入。
父类委托:一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,父类加载器无法加载该类时才从自己的类路径中加载该类。
缓存机制:保证所有加载过的Class都会被缓存,程序需要使用某个Class对象时,类加载器从缓存区中搜索该Class,只有缓存区中不存在该Class对象时,才会读取该类对应的二进制数据,并将其转换为Class对象存储到缓存区。
ClassLoader是负责加载类的对象。其中的两个方法是:
static ClassLoader getSystemClassLoader()返回用于委派的系统类加载器。
ClassLoader getParent()返回父类加载器进行委派。
Java运行时具有以下内置类加载器:
Bootstrap class loader 是虚拟机的内置类加载器,通常表示为null,没有父null。
Platform class loader 平台类加载器可以看到所有平台类,平台类包括平台类加载器或其祖先定义的Java SE平台API,其实现类的JDK特定的运行时类。
System class loader 也被称为应用程序类加载器,与平台类加载器不同,系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类。
System的父加载器为Platform,Platform的父加载器为Bootstrap。
Java反射机制,是在运行时获取一个类的变量和方法信息,然后通过获取到的信息创建对象,调用方法。反射极大地增强程序的灵活性,程序不用在编译期就完成确定。
想要通过反射去使用一个类,首先要获取到该类的字节码文件对象,即Class类型的对象。方法有:
使用类的class属性来获取该类对应的Class对象。
调用对象的getClass()方法,返回对象所属类对应的Class对象。
使用Class类的静态方法forName(String className),要传入字符串参数,其值是一个类的全路径。
- public class getclass {
- public static void main(String[] args) throws ClassNotFoundException {
- Class
c1 = student.class; - System.out.println(c1);
-
- student stu = new student();
- Class extends student> c2 = stu.getClass();
- System.out.println(c2);
- }
- }
程序的输出是:
class student
class student
Class类中用于获取构造方法的方法有:
Constructor >[] getConstructors() 返回所有公共构造方法对象的数组。
Constructor >[] getDeclaredConstructors() 返回所有构造方法对象的数组。
Constructor
Constructor
Constructor类用于创建对象的方法是:
T newInstance(Object ...initargs)根据指定的构造方法创建对象。
- public class student {
- private String name;
- private int age;
- public student(){}
- public student(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 "the name is " + name + " and the age is " + age;
- }
- }
这是学生类,也是下面很多代码用到的。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- public class classget {
- public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
- Class
c = student.class; - Constructor>[] con1 = c.getConstructors();
- for(Constructor> c1:con1){
- System.out.println(c1);
- }
- System.out.println();
-
- Constructor>[] con2 = c.getDeclaredConstructors();
- for(Constructor> c2:con2){
- System.out.println(c2);
- }
- System.out.println();
-
- Constructor
con3 = c.getConstructor(); - System.out.println(con3);
- Constructor
con4 = c.getDeclaredConstructor(); - System.out.println(con4);
-
- Object obj = con3.newInstance();
- System.out.println(obj);
- }
- }
程序的输出是:
public student()
public student(java.lang.String,int)
public student()
public student(java.lang.String,int)
public student()
public student()
the name is null and the age is 0
基本数据类型也可以通过.class得到对应的Class类型。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- public class classtest1 {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Constructor
con = c.getConstructor(String.class,int.class); - Object obj = con.newInstance("Celia",22);
- System.out.println(obj);
- }
- }
程序的输出是:
the name is Celia and the age is 22
setAccessible()接收boolean类型值,为true则取消访问检查。
- public class student {
- private String name;
- private int age;
- public student(){}
- public student(String name,int age){
- this.name = name;
- this.age = age;
- }
-
- private student(String name){
- this.name = name;
- }
-
- 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 "the name is " + name + " and the age is " + age;
- }
- }
这里进行略微的修改,增加了一个private的构造方法,接收一个String类型参数,将其赋给name。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- public class classtest2 {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Constructor
con = c.getDeclaredConstructor(String.class); - con.setAccessible(true);
-
- Object obj = con.newInstance("Colin");
- System.out.println(obj);
- }
- }
程序的输出是:
the name is Colin and the age is 0
Class类获取成员变量的方法有:
Field[] getFields()返回所有公共成员变量对象的数组。
Field[] getDeclaredFields()返回所有成员变量对象的数组。
Field getField(String name)返回单个公共成员变量对象,名字是name。
Field getDeclaredField(String name)返回单个成员变量对象,名字是name。
Field类中用于给成员变量赋值的方法是:
void set(Object obj,Object value)给obj对象的成员变量赋值为value。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
-
- public class classfield1 {
- public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Field[] f1 = c.getFields();
- for(Field fi:f1){
- System.out.println(fi);
- }
- System.out.println();
-
- Field[] f2 = c.getDeclaredFields();
- for(Field fi:f2){
- System.out.println(fi);
- }
- System.out.println();
-
- Field f3 = c.getField("name");
- System.out.println(f3);
- Constructor
con = c.getConstructor(); - Object obj = con.newInstance();
- f3.set(obj,"Sixteen");
- System.out.println(obj);
- }
- }
这里已经提前将student类的name和age的权限改为public。
程序的输出是:
public java.lang.String student.name
public int student.age
public java.lang.String student.name
public int student.age
public java.lang.String student.name
the name is Sixteen and the age is 0
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
-
- public class classfield2 {
- public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Field f1 = c.getDeclaredField("name");
- f1.setAccessible(true);
- Constructor
con = c.getConstructor(); - Object obj = con.newInstance();
- f1.set(obj,"Paula");
-
- Field f2 = c.getDeclaredField("age");
- f2.setAccessible(true);
- f2.set(obj,22);
- System.out.println(obj);
- }
- }
这里已经提前将student类的name和age的权限改回private。
程序的输出是:
the name is Paula and the age is 22
Class类中获取成员方法的方法有:
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的。
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的。
Method getMethod(String name,Class> ...parameter Types)返回单个公共成员方法对象。
Method getDeclaredMethod(String name,Class> ... parameter Types)返回单个成员方法对象。
Method类用于调用成员方法的方法是:
Object invoke(Object obj,Object...args)调用obj对象的成员方法,参数是args,返回值是Object类型。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- public class classmethod1 {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Method[] m1 = c.getMethods();
- for(Method me:m1){
- System.out.println(me);
- }
- System.out.println();
-
- Method[] m2 = c.getDeclaredMethods();
- for(Method me:m2){
- System.out.println(me);
- }
- System.out.println();
-
- Method m3 = c.getMethod("toString");
- System.out.println(m3);
- Constructor
con = c.getConstructor(); - Object obj = con.newInstance();
- System.out.println(m3.invoke(obj));
- }
- }
程序的输出是:
public java.lang.String student.toString()
public java.lang.String student.getname()
public void student.setname(java.lang.String)
public int student.getage()
public void student.setage(int)
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() 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 student.toString()
public java.lang.String student.getname()
public void student.setname(java.lang.String)
public int student.getage()
public void student.setage(int)
public java.lang.String student.toString()
the name is null and the age is 0
- public class student {
- private String name;
- private int age;
- public student(){}
- public student(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 void method1(){
- System.out.println("Today is August 3rd, 2022");
- }
- public void method2(String str){
- System.out.println(str);
- }
-
- public void method3(String str,int num){
- int i;
- for(i = 0; i < num;i += 1){
- System.out.println(str);
- }
- }
- private void method4(){
- System.out.println("private");
- System.out.println("public");
- }
-
- public int method5(){
- return 10;
- }
- public String toString(){
- return "the name is " + name + " and the age is " + age;
- }
- }
在student类中多加了几个成员方法。
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- public class classmethod2 {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Class
c = student.class; - Constructor
con = c.getConstructor(); - Object obj = con.newInstance();
-
- Method m1 = c.getMethod("method1");
- m1.invoke(obj);
- System.out.println();
-
- Method m2 = c.getMethod("method2",String.class);
- m2.invoke(obj,"It is near the end!");
- System.out.println();
- Method m3 = c.getMethod("method3",String.class,int.class);
- m3.invoke(obj,"Haha",5);
- System.out.println();
-
- Method m4 = c.getDeclaredMethod("method4");
- m4.setAccessible(true);
- m4.invoke(obj);
- System.out.println();
-
- Method m5 = c.getMethod("method5");
- int num = (int) m5.invoke(obj);
- System.out.println(num);
- }
- }
程序的输出是:
Today is August 3rd, 2022
It is near the end!
Haha
Haha
Haha
Haha
Haha
private
public
10
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- public class classtest3 {
- public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
- ArrayList
al = new ArrayList(); - al.add(10);
- al.add(15);
- al.add(20);
- al.add(25);
-
- Class extends ArrayList> c = al.getClass();
- Method m = c.getMethod("add",Object.class);
- m.invoke(al,"Hello");
- m.invoke(al,"Java");
- System.out.println(al);
- }
- }
程序最初规定al存放Integer类型数据,下面使用泛型使其能加入其他数据。
程序的输出是:
[10, 15, 20, 25, Hello, Java]
- public class ateacher {
- public void teach(){
- System.out.println("Teach seriously");
- }
- }
- public class astudent {
- public void study(){
- System.out.println("Study hard");
- }
- }
这是用到的两个工具类。
这是文件指定的内容:
classname=astudent
methodname=study
- import java.io.FileNotFoundException;
- import java.io.FileReader;
- import java.io.IOException;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.Properties;
-
- public class classtest4 {
- public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
- Properties pro = new Properties();
- FileReader fr = new FileReader("class.txt");
- pro.load(fr);
- fr.close();
-
- String classname = pro.getProperty("classname");
- String methodname = pro.getProperty("methodname");
-
- Class> c = Class.forName(classname);
- Constructor> con = c.getConstructor();
- Object obj = con.newInstance();
- Method m = c.getMethod(methodname);
- m.invoke(obj);
-
- }
- }
程序的输出是:
Study hard
将指定的内容修改为下面的内容:
classname=ateacher
methodname=teach
程序的输出是:
Teach seriously
那么Java的所有三十六篇笔记就结束了,从8月4日到现在,用了大约二十天,将前面看视频的笔记整理了一下。在文章划分上,尽量将同一块知识点放在一块。现在对Java有了一定的掌握程度,接下来就该看书进阶了。就目前知识来讲Java难度尚可,后面的进阶路线比较长。现在我已经线上大二开学,在家上网课,估计会上不到一个月网课。总之,接下来该继续努力了。