反射
-
類加載器
-
類加載
類加載的描述
當程序要使用某個類時,如果該類還未被加載到內存中,則系統會通過類的加載,類的連接,類的初始化這三個步驟來對類進行初始化。如果不出現意外情況,JVM將會連續完成這三個步驟,所以有時也把這三個步驟統稱爲類加載或者類初始化
類的加載
- 就是指將class文件讀入內存,併爲之創建一個 java.lang.Class 對象
- 任何類被使用時,系統都會爲之建立一個 java.lang.Class 對象類的連接
/*
ClassLoader 中的兩個方法
static ClassLoader getSystemClassLoader():返回用於委派的系統類加載器
ClassLoader getParent():返回父類加載器進行委派
*/
public class Test {
public static void main(String[] args) {
//static ClassLoader getSystemClassLoader():返回用於委派的系統類加載器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader); //AppClassLoader
//ClassLoader getParent():返回父類加載器進行委派
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent); //PlatformClassLoader
ClassLoader c3 = parent.getParent();
System.out.println(c3); //null
}
}
/*
jdk.internal.loader.ClassLoaders$AppClassLoader@78308db1
jdk.internal.loader.ClassLoaders$PlatformClassLoader@2d98a335
null
*/
-
反射
-
反射的概述
是指在運行時去獲取一個類的變量和方法信息。然後通過獲取到的信息來創建對象,調用方法的一種機制。由於這種動態性,可以極大的增強程序的靈活性,程序不用在編譯期就完成確定,在運行期仍然可以擴展
/*
三種方式獲取Class對象
1:使用類的class屬性來獲取該類對應的Class對象。舉例:Student.class將會返回Student類對應的Class對象
2:調用對象的getClass()方法,返回該對象所屬類對應的Class對象
該方法是Object類中的方法,所有的Java對象都可以調用該方法
3:使用Class類中的靜態方法forName(String className),該方法需要傳入字符串參數,該字符串參數的值是某個類的全路徑,也就是完整包名的路徑
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//使用類的class屬性來獲取該類對應的Class對象
Class<Student> stuClass = Student.class;
System.out.println(stuClass);
Class<Student> stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);
System.out.println("----------------------");
//調用對象的getClass()方法,返回該對象所屬類對應的Class對象
Student stu = new Student();
Class<? extends Student> stuClass3 = stu.getClass();
System.out.println(stuClass == stuClass3);
System.out.println("----------------------");
//使用Class類中的靜態方法forName(String className)
Class<?> stuClass4 = Class.forName("com.Reflect.Student");
System.out.println(stuClass == stuClass4);
}
}
/*
class com.Reflect.Student
true
----------------------
true
----------------------
true
*/
-
反射獲取構造方法並使用
方法名 |
說明 |
Constructor<?>[] getConstructors() |
返回所有公共構造方法對象的數組 |
Constructor<?>[] getDeclaredConstructors() |
返回所有構造方法對象的數組 |
Constructor getConstructor(Class<?>... parameterTypes) |
返回單個公共構造方法對象 |
Constructor getDeclaredConstructor(Class<?>... parameterTypes) |
返回單個構造方法對象 |
package com.Reflect;
public class Student {
//成員變量:一個私有,一個默認,一個公共
private String name;
int age;
public String address;
//構造方法:一個私有,一個默認,兩個公共
public Student() {
}
private Student(String name) {
this.name = name;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//成員方法:一個私有,四個公共
private void function() {
System.out.println("function");
}
public void method1() {
System.out.println("method");
}
public void method2(String s) {
System.out.println("method:" + s);
}
public String method3(String s, int i) {
return s + "," + i;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
/*
反射獲取構造方法並使用獲取對象
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class對象
Class<?> stuClass = Class.forName("com.Reflect.Student");
//Constructor<?>[] getConstructors() 返回一個包含 Constructor對象的數組, Constructor對象反映了由該 Class對象表示的類的所有公共構造函數
Constructor<?>[] publicConstructors = stuClass.getConstructors(); //公共構造方法數組
for (Constructor<?> stuCon : publicConstructors) System.out.println(stuCon);
System.out.println("------------------");
//Constructor<?>[] getDeclaredConstructors() 返回反映由該 Class對象表示的類聲明的所有構造函數的 Constructor對象的數組
Constructor<?>[] allConstructors = stuClass.getDeclaredConstructors(); //所有構造方法數組
for (Constructor<?> stuCon : allConstructors) System.out.println(stuCon);
System.out.println("------------------");
//Constructor提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
Constructor<?> stuConstructor = stuClass.getConstructor();
//T newInstance(Object... initargs) 使用由此 Constructor對象表示的構造函數,使用指定的初始化參數來創建和初始化構造函數的聲明類的新實例
Object student = stuConstructor.newInstance();
System.out.println(student);
}
}
/*
public com.Reflect.Student(java.lang.String,int,java.lang.String)
public com.Reflect.Student()
------------------
public com.Reflect.Student(java.lang.String,int,java.lang.String)
com.Reflect.Student(java.lang.String,int)
private com.Reflect.Student(java.lang.String)
public com.Reflect.Student()
------------------
Student{name='null', age=0, address='null'}
*/
獲取構造方法初始化對象
通過反射獲取公共的構造方法並創建對象
/*
反射獲取構造方法並使用獲取對象
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class對象
Class<?> student = Class.forName("com.Reflect.Student");
//Constructor提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
//public Student(String name, int age, String address)
Constructor<?> stuConstructor = student.getConstructor(String.class, int.class, String.class);
//T newInstance(Object... initargs) 由Constructor對象表示的構造函數來創建和初始化構造函數的聲明類的新實例
Object stu = stuConstructor.newInstance("李茂貞", 25, "岐國");
System.out.println(stu);
}
}
/*
Student{name='李茂貞', age=25, address='岐國'}
*/
/*
暴力反射
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class對象
Class<?> student = Class.forName("com.Reflect.Student");
//Constructor 提供了一個類的單個構造函數的信息和訪問權限 Constructor<?> con = c.getConstructor();
//反射 私有 構造方法private Student(String name)
Constructor<?> stuConstructor = student.getDeclaredConstructor(String.class);
//暴力反射
//將此反射對象的accessible標誌設置爲指示的布爾值。 值爲true表示反射對象應該在使用Java語言訪問控制時抑制檢查。 值爲false表示反射對象應該在使用Java語言訪問控制時執行檢查,並在類描述中指出變體。
//public void setAccessible(boolean flag):值爲true,取消訪問檢查
stuConstructor.setAccessible(true);
//T newInstance(Object... initargs) 由Constructor對象表示的構造函數來創建和初始化構造函數的聲明類的新實例
Object stu = stuConstructor.newInstance("李茂貞");
System.out.println(stu);
}
}
/*
Student{name='李茂貞', age=0, address='null'}
*/
-
Class類獲取成員變量對象的方法
方法分類
方法名 |
說明 |
Field[] getFields() |
返回所有公共成員變量對象的數組 |
Field[] getDeclaredFields() |
返回所有成員變量對象的數組 |
Field getField(String name) |
返回單個公共成員變量對象 |
Field getDeclaredField(String name) |
返回單個成員變量對象 |
方法名 |
說明 |
voidset(Object obj,Object value) |
給obj對象的成員變量賦值爲value |
/*
反射獲取成員變量並使用
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
//獲取Class對象
Class<?> student = Class.forName("com.Reflect.Student");
//Field[] getFields() 返回一個包含 Field對象的數組, Field對象反映由該 Class對象表示的類或接口的所有可訪問的公共字段
Field[] fields1 = student.getFields();
//Field[] getDeclaredFields() 返回一個 Field對象的數組,反映了由該 Class對象表示的類或接口聲明的所有字段
Field[] declaredFields = student.getDeclaredFields();
for (Field fi : declaredFields) System.out.println(fi);
System.out.println("----------------------------");
//Field getField(String name) 返回一個 Field對象,該對象反映由該 Class對象表示的類或接口的指定公共成員字段
Field address = student.getField("address");
//Field getDeclaredField(String name) 返回一個 Field對象,該對象反映由該 Class對象表示的類或接口的指定聲明字段
Field name = student.getDeclaredField("name");
//獲取無參構造方法創建對象
Constructor<?> stuConstructor = student.getConstructor();
//獲取Student類對象
Object stu = stuConstructor.newInstance();
//Field提供有關類或接口的單個字段的信息和動態訪問
//void set(Object obj, Object value) 將指定的對象參數中由此 Field對象表示的字段設置爲指定的新值
address.set(stu, "岐國"); //addressField.set(stu, "岐國"); //給stu的成員變量address賦值爲岐國
name.setAccessible(true);
name.set(stu, "李茂貞"); //IllegalAccessException,前面添加 name.setAccessible(true);暴力反射
System.out.println(stu);
}
}
/*
private java.lang.String com.Reflect.Student.name
int com.Reflect.Student.age
public java.lang.String com.Reflect.Student.address
----------------------------
Student{name='李茂貞', age=0, address='岐國'}
*/
/*
反射獲取成員變量並使用
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, NoSuchMethodException {
Class student = Class.forName("com.Reflect.Student");
Constructor<?> stuConstructor = student.getConstructor();
Object stu = stuConstructor.newInstance();
//name = "李茂貞"
Field name = student.getDeclaredField("name");
name.setAccessible(true);
name.set(stu, "李茂貞");
//age = 25
Field age = student.getDeclaredField("age");
age.setAccessible(true);
age.set(stu, 25);
//address = "岐國"
Field address = student.getDeclaredField("address");
address.setAccessible(true);
address.set(stu, "岐國");
System.out.println(stu);
}
}
/*
Student{name='李茂貞', age=25, address='岐國'}
*/
-
反射獲取成員變量並使用練習
Class類獲取成員方法對象的方法 方法分類
方法名 |
說明 |
Method[] getMethods() |
返回所有公共成員方法對象的數組,包括繼承的 |
Method[] getDeclaredMethods() |
返回所有成員方法對象的數組,不包括繼承的 |
Method getMethod(String name, Class<?>... parameterTypes) |
返回單個公共成員方法對象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) |
返回單個成員方法對象 |
/*
反射獲取成員方法並使用
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class對象
Class student = Class.forName("com.Test.Student");
//Method[] getMethods() 返回一個包含 方法對象的數組, 方法對象反映由該 Class對象表示的類或接口的所有公共方法,包括由類或接口聲明的對象以及從超類和超級接口繼承的類
//獲取本類所有父類的公共方法
//Method[] methods1 = student.getMethods();
//Method[] getDeclaredMethods() 返回一個包含 方法對象的數組, 方法對象反映由 Class對象表示的類或接口的所有聲明方法,包括public,protected,default(package)訪問和私有方法,但不包括繼承方法
Method[] declaredMethods = student.getDeclaredMethods();
for (Method method: declaredMethods) System.out.println(method);
System.out.println("---------------------");
//Method getMethod(String name, Class<?>... parameterTypes) 返回一個 方法對象,該對象反映由該 Class對象表示的類或接口的指定公共成員方法
//Method getDeclaredMethod(String name, Class<?>... parameterTypes) 返回一個 方法對象,它反映此表示的類或接口的指定聲明的方法 Class對象
Method dMethod = student.getDeclaredMethod("method1");
//獲取無參構造方法創建對象
Constructor stuCon = student.getConstructor();
Object stu = stuCon.newInstance();
//在類或接口上提供有關單一方法的信息和訪問權限
//Object invoke(Object obj, Object... args) 在具有指定參數的指定對象上調用此 方法對象表示的基礎方法
//Object:返回值類型
//obj:調用方法的對象
//args:方法需要的參數
dMethod.invoke(stu);
}
}
/*
public java.lang.String com.Test.Student.toString()
private void com.Test.Student.function()
public void com.Test.Student.method1()
public java.lang.String com.Test.Student.method3(java.lang.String,int)
public void com.Test.Student.method2(java.lang.String)
---------------------
method
*/
/*
練習:通過反射實現如下操作
Student s = new Student();
s.method1();
s.method2("林青霞");
String ss = s.method3("林青霞",30);
System.out.println(ss);
s.function();
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//獲取Class對象
Class student = Class.forName("com.Test.Student");
//Student s = new Student();
Constructor stuCon = student.getConstructor();
Object stu = stuCon.newInstance();
//s.method1();
Method method1 = student.getMethod("method1");
method1.invoke(stu);
//s.method2("林青霞");
Method method2 = student.getMethod("method2", String.class);
method2.invoke(stu, "李茂貞");
// String ss = s.method3("林青霞",30);
// System.out.println(ss);
Method method3 = student.getMethod("method3", String.class, int.class);
Object rensult = method3.invoke(stu, "李茂貞", 25);
System.out.println(rensult);
System.out.println((String)rensult);
//s.function(); //private void function()
// Method m4 = c.getMethod("function"); //NoSuchMethodException: com.itheima_02.Student.function()
Method function = student.getDeclaredMethod("function");
function.setAccessible(true);
function.invoke(stu);
}
}
/*
method
method:李茂貞
李茂貞,25
李茂貞,25
function
*/
-
反射練習之越過泛型檢查
/*
練習1:我有一個ArrayList<Integer>集合,現在我想在這個集合中添加一個字符串數據,如何實現?
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//創建集合
ArrayList<Integer> array = new ArrayList<>();
array.add(10);
array.add(50);
array.add(90);
System.out.println(array);
//獲取Classd對象
Class<? extends ArrayList> arrayClass = array.getClass();
Method add = arrayClass.getDeclaredMethod("add", Object.class);
add.invoke(array, "hello");
add.invoke(array, "reflect");
System.out.println(array);
}
}
/*
[10, 50, 90]
[10, 50, 90, hello, reflect]
*/
-
運行配置文件中指定類的指定方法
/*
練習2:通過配置文件運行類中的方法
*/
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException {
/* Teacher tea = new Teacher();
tea.teach();
Student stu = new Student();
//private void study
*/
/*
class.txt
className=xxx
methodName=xxx
*/
//加載數據
FileReader fr = new FileReader("E:\\work_space\\java_work\\java_test\\src\\com\\Test\\conf.txt");
Properties prop = new Properties();
prop.load(fr);
System.out.println(prop);
//通過反射來調用方法
Class obClass = Class.forName(prop.getProperty("className"));
Constructor constructor = obClass.getConstructor();
Object o = constructor.newInstance();
Method method = obClass.getDeclaredMethod(prop.getProperty("methodName"));
method.setAccessible(true);
method.invoke(o);
//通過反射來調用方法
Class obClass2 = Class.forName(prop.getProperty("className2"));
Constructor constructor2 = obClass2.getConstructor();
Object o2 = constructor2.newInstance();
Method method2 = obClass2.getDeclaredMethod(prop.getProperty("methodName2"));
method2.setAccessible(true);
method2.invoke(o2);
}
}
/*
{methodName=teach, methodName2=study, className=com.Test.Teacher, className2=com.Test.Student}
老師教學!
學生學習!
*/
-
模塊化
Java語言隨着這些年的發展已經成爲了一門影響深遠的編程語言,無數平臺,系統都採用Java語言編寫。但是,伴隨着發展,Java也越來越龐大,逐漸發展成爲一門“臃腫” 的語言。而且,無論是運行一個大型的軟件系統,還是運行一個小的程序,即使程序只需要使用Java的部分核心功能, JVM也要加載整個JRE環境。 爲了給Java“瘦身”,讓Java實現輕量化,Java 9正式的推出了模塊化系統。Java被拆分爲N多個模塊,並允許Java程序可以根據需要選擇加載程序必須的Java模塊,這樣就可以讓Java以輕量化的方式來運行
其實,Java 7的時候已經提出了模塊化的概念,但由於其過於複雜,Java 7,Java 8都一直未能真正推出,直到Java 9才真正成熟起來。對於Java語言來說,模塊化系統是一次真正的自我革新,這種革新使得“古老而龐大”的Java語言重新煥發年輕的活力
package com.toroidal01;
public class Studnet {
public void study(){
System.out.println("學生學習!");
}
}
module myOne {
exports com.toroidal01;
}
module myTow {
requires myOne;
}
package com.toroidal;
import com.toroidal01.Studnet;
public class Test {
public static void main(String[] args) {
Studnet stu = new Studnet();
stu.study();
}
}
-
模塊服務的基本使用