這種方法賊牛X,也就是通過(guò)外部文件配置,在不修改源碼的情況下,來(lái)控制程序,也符合設計模式的 ocp原則(開(kāi)閉原則:不修改源碼,擴容功能)
可以通過(guò)修改properties 配置文件的method的配置,實(shí)現修改程序的表現方式。
舉例子:
src\re.properties 文件
classfullpath = opp3.Cat method=cry // 如果 cry 改為 hi 則會(huì )改變
Cat.class
package opp3;
public class Cat {
private String name = "招財";
public void hi(){
System.out.println("hi,招財");
}
public void cry(){
System.out.println("hi,喵喵叫");
}
}ReflectionQuestion.class
package opp3;
import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* 反射問(wèn)題的引入
*/
public class ReflectionQuestion {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//根據配置文件 re.properties 指定信息,創(chuàng )建Cat對象并調用hi方法
//傳統方法 new 對象——>調用方法
// Cat cat = new Cat();
// cat.hi();
//嘗試做 明白反射
//1. 使用properties類(lèi),可以讀寫(xiě)配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String method = properties.get("method").toString();
System.out.println(classfullpath);
System.out.println(method);
//2. 創(chuàng )建對象,傳統的方法就要用 反射機制
System.out.println("==========================================");
//3. 使用反射機制解決
//(1)加載類(lèi),返回Class類(lèi)型的對象
//(2)通過(guò)cls 得到加載的類(lèi) opp3.Cat 的對象實(shí)例
Class<?> cls = Class.forName(classfullpath);
Cat cat = (Cat) cls.newInstance();
System.out.println("運行類(lèi)型"+cat.getClass());
//(3)通過(guò) cls 得到你加載的類(lèi) opp3.Cat 的 hi 的方法對象
// 即:在反射中,可以把方法視為對象(萬(wàn)物皆對象)
Method method1 = cls.getMethod(method);
//通過(guò)method1 調用方法,即通過(guò)方法對象來(lái)實(shí)現調用方法
method1.invoke(cat); //反射機制 方法.invoke(對象) 傳統:對象.方法
}
}java.reflection
java.lang.Class:代表一個(gè)類(lèi),Class對象表示某個(gè)類(lèi)加載后在堆中的對象
java.lang.reflect.Method:代表類(lèi)的方法,Method對象表示某個(gè)類(lèi)的方法
java.lang.reflect.Field:代表類(lèi)的成員變量,Field對象表示某個(gè)類(lèi)的成員變量
java.lang.reflect.Constructor:代表類(lèi)的構造方法,Constructor表示構造器
這些類(lèi)在java.lang 包
package opp3;
public class Cat {
private String name = "招財";
public int age = 10;
public Cat(){} //無(wú)參構造器
public Cat(String name){ this.name = name; }
public void hi(){
System.out.println("hi,招財");
}
public void cry(){
System.out.println("hi,喵喵叫");
}
public static class demo01 {
}
}classfullpath = opp3.Cat method=cry
package opp3;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class demo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String method = properties.get("method").toString();
//2. 使用反射機制解決
//(1)加載類(lèi),返回Class類(lèi)型的對象
Class<?> cls = Class.forName(classfullpath);
//(2)通過(guò)cls 得到加載的類(lèi) opp3.Cat 的對象實(shí)例
Cat cat = (Cat) cls.newInstance();
System.out.println("運行類(lèi)型"+cat.getClass());
//(3)通過(guò) cls 得到你加載的類(lèi) opp3.Cat 的 hi 的方法對象
// 即:在反射中,可以把方法視為對象(萬(wàn)物皆對象)
Method method1 = cls.getMethod(method);
//通過(guò)method1 調用方法,即通過(guò)方法對象來(lái)實(shí)現調用方法
method1.invoke(cat); //反射機制 方法.invoke(對象) 傳統:對象.方法
//java.lang.reflect.Field 代表類(lèi)的成員變量,Field對象表示某個(gè)類(lèi)的成員變量
//得到name
//getField 不能得到private私有的屬性
// Field field = cls.getField("name"); //getField 不能得到private私有的屬性 private String name = "招財";
Field field = cls.getField("age");
// 傳統寫(xiě)法: 對象.成員變量 , 反射:成員變量對象.get(對象)
System.out.println(field.get(cat)); // public int age = 10;
//java.lang.reflect.Constructor 代表類(lèi)的構造方法,Constructor表示構造器
Constructor<?> constructor = cls.getConstructor(); // () 中可以指定構造器參數類(lèi)型 。括號里為空,則為無(wú)參構造器
System.out.println(constructor); //public opp3.Cat() public Cat(){} //無(wú)參構造器
Constructor<?> constructor1 = cls.getConstructor(String.class);//這里傳入的 String.class 就是String類(lèi)的Class對象
System.out.println(constructor1); //public opp3.Cat(java.lang.String) public Cat(String name){ this.name = name; }
}
}反射的
優(yōu)點(diǎn):可以動(dòng)態(tài)的創(chuàng )建和使用對象(也可以是框架底層核心),使用靈活,沒(méi)有反射機制,框架即時(shí)就是去底層支撐
缺點(diǎn):使用反射基本就是解釋執行,對執行速度有影響
package opp3;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class demo02 {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
m1();
m2();
}
//傳統方法
public static void m1(){
Cat cat = new Cat();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
cat.hi();
}
long endTime = System.currentTimeMillis();
System.out.println("傳統方法用時(shí):" + (endTime-startTime));
}
//反射機制
public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> cls = Class.forName("opp3.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
hi.invoke(o);
}
long endTime = System.currentTimeMillis();
System.out.println("反射機制用時(shí):" + (endTime-startTime));
}
}稍微優(yōu)化一下 setAccessible(true);
setAccessible:?jiǎn)?dòng)和禁用訪(fǎng)問(wèn)安全檢查的開(kāi)關(guān)。參數值為true則指反射的對象在使用時(shí)應該取消java語(yǔ)言訪(fǎng)問(wèn)檢查。
提高反射效率。如果代碼中必須使用反射,而該句代碼需要頻發(fā)的被調用,那么請設置為true
使得原本無(wú)法訪(fǎng)問(wèn)的私有成員也可以訪(fǎng)問(wèn)
package opp3;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class demo02 {
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
m1();
m2();
m3();
}
//傳統方法
public static void m1(){
Cat cat = new Cat();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
cat.hi();
}
long endTime = System.currentTimeMillis();
System.out.println("傳統方法用時(shí):" + (endTime-startTime));
}
//反射機制
public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> cls = Class.forName("opp3.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
hi.invoke(o);
}
long endTime = System.currentTimeMillis();
System.out.println("反射機制用時(shí):" + (endTime-startTime));
}
//反射優(yōu)化
public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class<?> cls = Class.forName("opp3.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
hi.setAccessible(true); //取消訪(fǎng)問(wèn)檢查
long startTime = System.currentTimeMillis();
for (int i = 0; i < 1000000000; i++) {
hi.invoke(o);
}
long endTime = System.currentTimeMillis();
System.out.println("反射機制用時(shí):" + (endTime-startTime));
}
}Method的setAccessible優(yōu)化
Method hi = cls.getMethod("hi");
hi.setAccessible(true);Field的setAccessible優(yōu)化
Field name = cls.getField("name");
name.setAccessible(true);
//因為原來(lái)的的屬性是private,不能直接訪(fǎng)問(wèn),所以需要關(guān)閉安全檢測 private String name = "招財";Class也是類(lèi),因此也繼承Object類(lèi)
Class類(lèi)對象不是new 出來(lái)的,而是系統生成的
對于某個(gè)類(lèi)的Class類(lèi)對象,在內存中只有一份,因此類(lèi)只加載一次
每個(gè)類(lèi)的實(shí)例都會(huì )記得自己是哪個(gè)Class實(shí)例所生成
通過(guò)Class可以完整地得到一個(gè)類(lèi)的完整結構,通過(guò)一些列API
Class對象是存放在堆中
類(lèi)的字節碼二進(jìn)制數據,是放在方法區,有的地方稱(chēng)為類(lèi)的元數據(包括 方法代碼,變量名,方法名,訪(fǎng)問(wèn)權限等等)

package opp3;
/**
* 演示getClass()
*/
public class GetClass {
public static void main(String[] args) throws ClassNotFoundException {
//1. Class.forName
// 需要知道目標類(lèi)的 的位置和類(lèi)名
String classPath = "opp3.Cat";
Class<?> cls1 = Class.forName(classPath);
System.out.println(cls1);
//2.類(lèi)名.class ,應用場(chǎng)景:用于參數傳遞
Class cls2 = Cat.class;
System.out.println(cls2);
//3. 對象.getClass() 運用場(chǎng)景:有對象實(shí)例
// 運行時(shí)
Cat cat = new Cat();
Class cls3 = cat.getClass();
System.out.println(cls3);
//4. 通過(guò)類(lèi)加載器【4種】獲取類(lèi)的Class對象
//(1)先得到類(lèi)加載器 cat
ClassLoader classLoader = cat.getClass().getClassLoader();
//(2)通過(guò)類(lèi)加載器得到Class對象
Class cls4 = classLoader.loadClass(classPath);
System.out.println(cls4);
//cls1 cls2 cls3 cls4 其實(shí)是同一個(gè)對象
//5. 基本數據類(lèi)型(int char boolean float double byte long short)按如下方式得到Class類(lèi)對象
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
Class<Boolean> booleanClass = boolean.class;
System.out.println(integerClass); //其他基本類(lèi)型就不展示了
//6. 基本數據類(lèi)型對應的包裝類(lèi),可以通過(guò) .TYPE 得到Class類(lèi)對象
Class<Integer> type = Integer.TYPE;
Class<Character> characterClass1 = Character.class; //其他包裝類(lèi)BOOLEAN DOUBLE BYTE 等也一樣
System.out.println(type);
}
}class:外部類(lèi)、成員(內部成員、外部成員),局部?jì)炔款?lèi),匿名內部類(lèi)
interface:接口
[] :數組
enum:枚舉
annotation:注解@interface
primitive type:基本數據類(lèi)型
void
package opp3;
import java.io.Serializable;
public class TypeClass {
public static void main(String[] args) {
ClassstringClass = String.class; //外部類(lèi)
ClassserializableClass = Serializable.class; //接口
ClassaClass = Integer[].class; //數組
ClassaClass1 = float[][].class; //二維數組
ClassdeprecatedClass = Deprecated.class; //注解
//枚舉
ClassstateClass = Thread.State.class;
ClasslongClass = long.class; //基本數據類(lèi)型
ClassvoidClass = void.class; //void數據類(lèi)型
ClassclassClass = Class.class;
System.out.println(stateClass);
System.out.println(serializableClass);
System.out.println(aClass);
System.out.println(aClass1);
System.out.println(deprecatedClass);
System.out.println(serializableClass);
System.out.println(longClass);
System.out.println(voidClass);
System.out.println(classClass);
}
}靜態(tài)加載:編譯時(shí)加載相關(guān)類(lèi),如果沒(méi)有則報錯,依賴(lài)性太強
動(dòng)態(tài)加載:運行時(shí)加載需要的類(lèi),如果運行時(shí)不用該類(lèi),則不報錯,降低依賴(lài)性
類(lèi)加載時(shí)機:
當創(chuàng )建對象時(shí)(new) //靜態(tài)加載
當子類(lèi)被加載時(shí),父類(lèi)也加載 //靜態(tài)加載
調用類(lèi)種的靜態(tài)成員時(shí) //靜態(tài)加載
通過(guò)反射
package opp3;
import java.lang.reflect.Method;
public class ClassLoad_ {
public static void main(String[] args) throws Exception {
// //靜態(tài)加載,依賴(lài)性很強
// //編譯前必須有Cat類(lèi),否則會(huì )報錯
// Cat cat = new Cat();
// cat.hi();
//靜態(tài)加載
//反射 -> 動(dòng)態(tài)加載
//因為是動(dòng)態(tài)加載,則就算編譯前沒(méi)有寫(xiě)有Cat類(lèi)也沒(méi)有報錯。
//只有當動(dòng)態(tài)加載到Cat類(lèi)時(shí),當發(fā)現沒(méi)有Cat類(lèi)時(shí),才會(huì )報錯
Class aClass = Class.forName("opp3.Cat");
Object o = aClass.newInstance(); //新建一個(gè)對象o
Method hi = aClass.getMethod("hi");
hi.invoke(o); //激活新建對象o 的hi方法
}
}一、加載
二、驗證階段:
目的是為了去額寶Class文件的字節流種包含的信息符合當前虛擬機的要求,并且不會(huì )危害虛擬機自身安全
包括:文件格式驗證(是否以魔數 oxcafebabe開(kāi)頭)、元數據驗證、字節碼驗證和符號引用驗證
可以考慮使用 -Xverify:none 參數來(lái)關(guān)閉大部分的類(lèi)驗證措施,縮短虛擬機加載時(shí)間(只要你項目足夠大,小項目就不考慮)
三、準備階段:
//1. n1 是實(shí)例屬性,不是靜態(tài)變量,因此在準備階段不會(huì )分配內存 //2. n2 是靜態(tài)變量,分配內存n2 是默認初始化 0 ,而不是20 //3. n3 是static final 常量,它和靜態(tài)變量不一樣,因為一旦賦值就不邊 n3 = 30 // class內部 //屬性-成員變量-字段 public int n1 = 10; public static int n2 = 20; public static final int n3 = 30
四、解析 階段
虛擬機將常量池內的符號引用替換為直接引用的過(guò)程
五、初始化
到初始化階段,才正在執行類(lèi)中定義的java程序代碼,此階段是執行()方法的過(guò)程
()方法是按語(yǔ)句在源文件中出現的順序,依次自動(dòng)收集類(lèi)中所有的靜態(tài)變量的賦值動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句,并進(jìn)行合并
虛擬機會(huì )保證一個(gè)類(lèi)()方法在多線(xiàn)程環(huán)境中被正確地加鎖、同步,如果多個(gè)線(xiàn)程同時(shí)去初始化一個(gè)類(lèi),那么只會(huì )有一個(gè)線(xiàn)程去執行這個(gè)類(lèi)的()方法,其他線(xiàn)程都需要阻塞等待,知道活動(dòng)線(xiàn)程執行()方法完畢。
第一組:
getName(); 獲取全類(lèi)名
getSimpleName(); 獲取簡(jiǎn)單類(lèi)名
getFields(); 獲取所有public修飾的屬性,包括父類(lèi)的
getDeclaredFields(); 獲取本類(lèi)中所有屬性
getMethods(); 獲取多有的public修飾的方法,包括父類(lèi)的
getDeclaredMethods(); 獲取本類(lèi)所有的方法
getConstructors(); 獲取本類(lèi)所有public修飾的構造器
getDeclaredConstructors(); 獲取本類(lèi)中所有的構造器
getPackage(); 以package形式返回父類(lèi)信息
getSuperclass(); 以class形式返回父類(lèi)信息
getInterfaces(); 以Class[]形式返回接口信息
getAnnotations(); 以Annotations[]形式返回注解信息
package opp3;
import org.testng.annotations.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 如何獲取類(lèi)的結構信息
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
api_01();
}
@Test
public static void api_01() throws Exception {
/**
* 1. getName(); 獲取全類(lèi)名
* 2. getSimpleName(); 獲取簡(jiǎn)單類(lèi)名
* 3. getFields(); 獲取所有public修飾的屬性,包括父類(lèi)的
* 4. getDeclaredFields(); 獲取本類(lèi)中所有屬性
* 5. getMethods(); 獲取多有的public修飾的方法,包括父類(lèi)的
* 6. getDeclaredMethods(); 獲取本類(lèi)所有的方法
* 7. getConstructors(); 獲取本類(lèi)所有public修飾的構造器,
* 8. getDeclaredConstructors(); 獲取本類(lèi)中所有的構造器
* 9. getPackage(); 以package形式返回父類(lèi)信息
* 10. getSuperclass(); 以class形式返回父類(lèi)信息
* 11. getInterfaces(); 以Class[]形式返回接口信息
* 12. getAnnotations(); 以Annotations[]形式返回注解信息
*/
Class cls = Class.forName("opp3.Person");
System.out.println(cls.getName());
System.out.println(cls.getSimpleName());
Field[] fields = cls.getFields();
for (Field field : fields) {
System.out.println("本類(lèi)及父類(lèi)的屬性" + field);
}
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本類(lèi)的屬性 " + declaredField);
}
Method[] methods = cls.getMethods();
for (Method method : methods) {
System.out.println("本類(lèi)及父類(lèi)method: " + method.getName());
}
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本類(lèi)所有方法" + declaredMethod.getName());
}
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("本類(lèi)constructors: " + constructor);
}
Constructor[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("本類(lèi)的declaredConstructors: " + declaredConstructor.getName()); //這里只是輸出了名字
}
System.out.println(cls.getPackage());
System.out.println(cls.getSuperclass());
Class[] interfaces = cls.getInterfaces();
for (Class anInterface : interfaces) {
System.out.println("接口信息:" + anInterface);
}
Annotation[] annotations = cls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("注解信息" + annotation);
}
}
}
class A {
public String hobby;
public A(){}
}
interface IA{
}
interface IB{
}
@Deprecated
class Person extends A implements IA,IB{
public String name;
protected int age;
String job;
private double sal;
public void m1(){}
protected void m2(){}
void m3(){}
//構造器
public Person(){}
public Person(String name){}
private Person(String name, int age){
}
}第二組:java.lang.reflect.Field類(lèi)
getModifiers :以int 形式返回修飾符
(說(shuō)明:默認修飾符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)
其他的舉例說(shuō)明:修飾符 public static:1+8 = 9
getType:以Class形式返回類(lèi)型
getName : 返回屬性名
public void api_02() throws Exception{
Class cls = Class.forName("opp3.Person");
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本類(lèi)的所有屬性 " + declaredField.getName()
+" 該屬性的修飾符值 " + declaredField.getModifiers()
+ " 該屬性的類(lèi)型 " + declaredField.getType());
}
}第三組:java.lang.reflect.Method類(lèi)
getModifiers :以int 形式返回修飾符
(說(shuō)明:默認修飾符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)
getReturnType: 以Class形式獲取 返回類(lèi)型
getName:返回方法名
getParameterTypes:以Class[]返回參數類(lèi)型數組
package opp3;
import org.testng.annotations.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* 如何獲取類(lèi)的結構信息
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
api_01();
}
@Test
public void api_02() throws Exception{
Class cls = Class.forName("opp3.Person");
Field[] declaredFields = cls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本類(lèi)的所有屬性 " + declaredField.getName()
+" 該屬性的修飾符值 " + declaredField.getModifiers()
+ " 該屬性的類(lèi)型 " + declaredField.getType());
}
Method[] declaredMethods = cls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本類(lèi)所有方法:" + declaredMethod.getName()
+" 該方法的訪(fǎng)問(wèn)修飾符值:"+declaredMethod.getModifiers()
+" 該方法的返回類(lèi)型:" + declaredMethod.getReturnType()
);
//輸出當前這個(gè)方法的形參數組情況
Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("該方法的形參類(lèi)型:" + genericParameterType);
}
}
}
}
class A {
public String hobby;
public A(){}
}
interface IA{
}
interface IB{
}
@Deprecated
class Person extends A implements IA,IB{
public String name;
protected int age;
protected static int id; //修飾符值 : 4 + 8 = 12
String job;
private double sal;
public void m1(String name,int age,double sal){}
protected String m2(){
return null;
}
void m3(){}
//構造器
public Person(){}
public Person(String name){}
private Person(String name, int age){
}
}第四組:java.lang.reflect.Constructor類(lèi)
getModifiers :以int 形式返回修飾符
(說(shuō)明:默認修飾符是0 , public 是1 , private是2, protected是 4 ,static是8, final 是16)
getName:返回構造器名(全類(lèi)名)
getParameterTypes:以Class[]返回參數類(lèi)型數組
package opp3;
import org.testng.annotations.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
/**
* 如何獲取類(lèi)的結構信息
*/
public class Demo05 {
public static void main(String[] args) throws Exception{
api_01();
}
@Test
public void api_02() throws Exception{
Class cls = Class.forName("opp3.Person");
Constructor[] declaredConstructors = cls.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("============================");
System.out.println("本類(lèi)的declaredConstructors: " + declaredConstructor.getName()); //這里只是輸出了名字
Class[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class parameterType : parameterTypes) {
System.out.println("該構造器的形參類(lèi)型:" + parameterType);
}
}
}
}
class A {
public String hobby;
public A(){}
}
interface IA{
}
interface IB{
}
@Deprecated
class Person extends A implements IA,IB{
public String name;
protected int age;
protected static int id; //修飾符值 : 4 + 8 = 12
String job;
private double sal;
public void m1(String name,int age,double sal){}
protected String m2(){
return null;
}
void m3(){}
//構造器
public Person(){}
public Person(String name){}
private Person(String name, int age){
}
}方式一:調用類(lèi)中的public修飾的無(wú)參構造器
方式二:調用類(lèi)中的指定構造器
Class類(lèi)相關(guān)方法
newInstance:調用類(lèi)中的無(wú)參構造器,獲取對應類(lèi)的對象
getConstructor(Class...clazz):根據參數列表,獲取對應的構造器對象
getDecalaredConstructor(Class...clazz):根據參數列表,獲取對應的構造器對象
Constructor類(lèi)相關(guān)說(shuō)法
setAccessible:爆破
newInstance(Object...obj):調用構造器
package opp3;
import java.lang.reflect.Constructor;
/**
* 通過(guò)反射機制創(chuàng )建實(shí)例
*/
public class Demo06 {
public static void main(String[] args) throws Exception {
//1. 獲取User類(lèi)的Class對象
Class<?> cls = Class.forName("opp3.User");
//2.通過(guò)public的無(wú)參構造器創(chuàng )建實(shí)例
Object o = cls.newInstance();
System.out.println(o);
//3.通過(guò)public的有參構造器創(chuàng )建實(shí)例
//此時(shí)此刻的constructor對象:
/*
public User(String name){ //public的有參構造器
this.name = name;
}
*/
//3.1 先得到對應的構造器
Constructor<?> constructor = cls.getConstructor(String.class);
//3.2 創(chuàng )建實(shí)例,并換入實(shí)參
Object o1 = constructor.newInstance("納西妲");
System.out.println(o1);
//4.通過(guò)非public的有參構造器創(chuàng )建實(shí)例
//4.1 先得到私有private 的構造器
/*
private User(int age, String name) { //private的有參構造器
this.age = age;
this.name = name;
}
*/
Constructor declaredConstructors = cls.getDeclaredConstructor(int.class, String.class);
//因為是私有的構造器,所以需要 declaredConstructors.setAccessible(true); 【爆破】
//4.2 創(chuàng )建實(shí)例
declaredConstructors.setAccessible(true);
Object o2 = declaredConstructors.newInstance(6000, "摩拉克斯");
System.out.println(o2);
}
}
class User{
private int age = 500;
private String name = "Nahida";
public User(){ //無(wú)參構造器 public
}
private User(int age, String name) { //private的有參構造器
this.age = age;
this.name = name;
}
public User(String name){ //public的有參構造器
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}如何通過(guò)反射訪(fǎng)問(wèn)類(lèi)中的成員
根據屬性名獲取Field對象
Field f = clazz 對象.getDeclaredField(屬性名)
爆破:f.setAccessible(true) //f是Field
訪(fǎng)問(wèn)
f.set(o,值); //o表示對象
syso(f.get(o)); // o表示對象
如果是靜態(tài)屬性,則set和get中的參數o,可以寫(xiě)成null
package opp3;
import java.lang.reflect.Field;
/**
* 反射操作屬性
*/
public class Demo07 {
public static void main(String[] args) throws Exception {
//1.得到Student對應的Class對象
Class<?> aClass = Class.forName("opp3.Student");
//2. 創(chuàng )建對象
Object o = aClass.newInstance(); //o 運行類(lèi)型就是Student
System.out.println(o);
//3. 使用反射得到 age 屬性對象
Field age = aClass.getField("age");
age.set(o,88); //通過(guò)反射操作屬性,設置age屬性的值為88
System.out.println(o);
System.out.println(age.get(o)); //返回age屬性的值
//4. 使用反射操作name屬性
Field name = aClass.getDeclaredField("name");
//name 在類(lèi)中是private私有的,需要setAccessible(true)
name.setAccessible(true);
// name.set(o,"巴巴托斯"); 也可以如下一句:
name.set(null,"巴巴托斯"); //因為name是靜態(tài)static的,所以 o 也可以是null, 【注意】不是靜態(tài)的的這么寫(xiě)會(huì )報錯
System.out.println(o);
System.out.println(name.get(o)); //獲取屬性值
}
}
class Student{
public int age; //公共 age
public static String name;
public Student(){ //構造器
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
",name=" + name +
'}';
}
}如何通過(guò)反射訪(fǎng)問(wèn)類(lèi)中的成員
訪(fǎng)問(wèn)方法:
根據方法名獲取Method方法對象
Method f = clazz 對象.getDeclaredMethod(方法名, XX.class) //得到本類(lèi)所有方法
獲取對象:Object o = clazz.newInstance();
爆破:m.setAccessible(true); //m是Method
訪(fǎng)問(wèn)
Object returnValue = m.invoke(o,實(shí)參列表);
如果是靜態(tài)屬性,則invoke中的參數o,可以寫(xiě)成null
package opp3;
import java.lang.reflect.Method;
/**
* 演示反射調用發(fā)發(fā)
*/
public class Demo08 {
public static void main(String[] args) throws Exception {
//1. 得到Boss 類(lèi)對應Class對象
Class<?> aClass = Class.forName("opp3.Boss");
//2. 創(chuàng )建對象
Object o = aClass.newInstance();
//3. 調用public 的hi方法
// Method hi = aClass.getMethod("hi", String.class); //getMethod() 獲取公共方法,這里可行,但是私有方法不行不能用
//得到hi方法
Method hi1 = aClass.getDeclaredMethod("hi", String.class); //getDeclaredMethod() 獲得類(lèi)的所有方法,這里也可行
hi1.invoke(o,"香菱");
//4. 調用私有方法
Method say = aClass.getDeclaredMethod("say", int.class, String.class, char.class);
say.setAccessible(true);
System.out.println(say.invoke(o,20,"云堇",'女'));
//因為say方法是靜態(tài)的,還可以這么寫(xiě): o 寫(xiě)成null
System.out.println(say.invoke(null,17,"胡桃",'女'));
//返回值:
//5. 在反射中,如果方法有返回值,統一返回object,但是它運行類(lèi)型和方法定義的返回類(lèi)型一致
Object invoke = say.invoke(null, 16, "行秋", '男');
System.out.println("invoke的運行類(lèi)型:" + invoke.getClass());
}
}
class Boss{
public int age;
private static String name;
public Boss(){
}
private static String say(int n, String s , char c){
return n+ " " + s + " " + c;
}
public void hi(String s){
System.out.println("hi " + s);
}
}package opp3.opp32;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class HomeWork {
public static void main(String[] args) throws Exception {
//1. 得到PrivateTest類(lèi)對應的Class對象
Class<?> cls = Class.forName("opp3.opp32.PrivateTest");
//2. 創(chuàng )建對象實(shí)例
Object o = cls.newInstance();
//3. 得到name屬性
Field name = cls.getDeclaredField("name");
//4. 爆破
name.setAccessible(true);
name.set(o,"七七");
//5. 獲得getName方法對象
Method getName = cls.getDeclaredMethod("getName");
//6. 因為getName是公有的,所以直接輸出
Object invoke = getName.invoke(o);
System.out.println("name的屬性值:" + invoke );
}
}
class PrivateTest{
private String name = "HelloKitty";
public String getName(){
return name;
}
}package opp3.opp32;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class HomeWork02 {
public static void main(String[] args) throws Exception {
//1. 利用Class類(lèi)的forName 得到File類(lèi)的class對象
Class<?> cls = Class.forName("java.io.File");
//2. 獲得所有的構造器
Constructor<?>[] declaredConstructors = cls.getDeclaredConstructors();
//遍歷輸出所有的的構造器
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("File的構造器:" + declaredConstructor);
}
//3. 單獨的得到public java.io.File(java.lang.String)
Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class);
String filePath = "e://mynew.txt";
Object file = declaredConstructor.newInstance(filePath); //創(chuàng )建文件File對象
//4. 調用createNewFile()方法,創(chuàng )建文件
Method createNewFile = cls.getDeclaredMethod("createNewFile");
createNewFile.invoke(file);
//file 的運行類(lèi)型就是File
System.out.println(file.getClass());
System.out.println("文件創(chuàng )建成功");
}
}
聯(lián)系客服