欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中反射reflect的基礎(chǔ)知識(shí)講解

 更新時(shí)間:2023年10月19日 10:36:05   作者:發(fā)光吖  
這篇文章主要介紹了Java中反射reflect的基礎(chǔ)知識(shí)講解,Java中的反射,它算是Java當(dāng)中非常底層的一個(gè)技術(shù),平時(shí)我們我們用得不多,實(shí)際上它也的確非常復(fù)雜同時(shí)也難以理解,但是涉及到底層的東西Java都給我們封裝好了,我們直接拿來調(diào)用即可,需要的朋友可以參考下

前言

Java中的反射,它算是Java當(dāng)中非常底層的一個(gè)技術(shù)。平時(shí)我們我們用得不多,實(shí)際上它也的確非常復(fù)雜同時(shí)也難以理解,但是涉及到底層的東西Java都給我們封裝好了,我們直接拿來調(diào)用即可,所以我們操作起來就很簡(jiǎn)單,這也是Java封裝性的一個(gè)體現(xiàn)。

理解反射

反射是java中提供的一種機(jī)制,它允許我們?cè)诔绦蜻\(yùn)行的時(shí)候,動(dòng)態(tài)獲取一個(gè)類中的基本信息,并且可以調(diào)用類中的屬性、方法、構(gòu)造器。

我們以往遵循的都是面向?qū)ο蟮木幊趟枷?,現(xiàn)實(shí)生活中,先存在了很多對(duì)象,它們有相同的特征,相同的行為,我們就把它們歸為一類,從一類對(duì)象中抽取出來的公有的特征行為以及抽象描述,用來描述一組對(duì)象,我們就把這一組對(duì)象抽象成一個(gè)類。在程序中,我們是先定義好一個(gè)類,進(jìn)而去new出一個(gè)該類的對(duì)象。

而反射卻不同,它是對(duì)于Java中對(duì)于類型的抽象,是對(duì)8種基本類型以及3種引用類型(類、接口、數(shù)組)的抽象?;绢愋偷姆瓷湮覀兒苌儆懻?,這里我們主要討論類的反射,它是最基礎(chǔ)最核心的。

反射機(jī)制可以認(rèn)為是用來描述一組類的。

Java中的反射大致可以分為幾個(gè)大的模塊:

  • Class 用來描述類本身
  • Package 用來描述類所屬的包
  • Field 用來描述類中的屬性
  • Method 用來描述類中的方法
  • Constructor 用來描述類中的構(gòu)造方法
  • Annotation 用來描述類中的注解(暫不討論)

Java中反射的入口:(Class)

它是java.lang包下的一個(gè)類,不需要導(dǎo)入即可使用,之所以說它是反射的入口,是因?yàn)槲覀兯械姆瓷洳僮鳎ò▽?duì)屬性、方法、構(gòu)造方法、注解)的全部操作,都是基于類來完成的。我們可以認(rèn)為類包含了屬性、方法、構(gòu)造方法、注解等,但是Java中為它們單獨(dú)定義了類(這些類都在java.lang.reflect包下),以此更好地描述這些類成員。

如何獲取Class(3種方式):

  • Class.forName(“類的全限定名”);

這種方式最靈活,但缺點(diǎn)是需要處理一個(gè)編譯時(shí)異常ClassNotFoundException,并且它不適用于數(shù)組的Class以及基本類型的Class獲取

  • 類名.class

這種方式最通用,它可以獲取到任何類型(包括基本類型)的Class

  • 對(duì)象.getClass()

這種方式依賴于對(duì)象,所以它不適用于接口和抽象類的Class獲取

Class中的常用方法

  • int modifiers = getModifiers() 獲取類的修飾符(權(quán)限 特征)

每一個(gè)修飾符,用一個(gè)整數(shù)來進(jìn)行表示,它們的數(shù)值剛好是二進(jìn)制中每一位上所代表的數(shù)字,這樣的好處是多個(gè)修飾符的數(shù)字進(jìn)行累加后的結(jié)果可以反推出所有的修飾符。它是通過按位與然后判斷結(jié)果是否為0來做到的,例如:

    public static boolean isPrivate(int mod) {
        return (mod & PRIVATE) != 0;
    }

PRIVATE是java.lang.reflect.Modifier類中定義的int類型的靜態(tài)常量,它的值為2,而PUBLIC的值為1,如果getModifiers()方法算出的修飾符數(shù)字為3(代表它是PUBLIC+PRIVATE修飾的),通過按位與,0011&0010得到的結(jié)果是0010,結(jié)果不為0,說明它是包含了PRIVATE修飾符的。

Modifier修飾符數(shù)值參照表:

修飾符數(shù)值
public1
private2
protected4
static8
final16
synchronized32
volatile64
transient128
native256
interface512
abstract1024
strictfp2048
  • String name = getName();獲取類的全限定名
  • String simpleName = getSimpleName();獲取類的簡(jiǎn)單名
  • String packageName = getPackage();獲取包
  • Class sclazz = getSuperClass();獲取超類(父類)
  • Class[] classes = getInterface();獲取該類實(shí)現(xiàn)的所有接口
  • Object obj = newInstance();默認(rèn)調(diào)用無參數(shù)構(gòu)造方法創(chuàng)建對(duì)象
  • Field f = getField(“屬性名”); Field[] fs = getFields(); 如上的兩個(gè)方法只能獲取公有的屬性 但是包含繼承過來的父類屬性
  • getDeclaredField(“屬性”); Field[] fs = getDeclaredFields(); 如上的兩個(gè)方法能獲取公有的和私有的屬性 但是只能獲取本類中的屬性
  • boolean = c2.isAssignableFrom(c1) 判斷c2代表的類型是不是c1代表的類型的父類型
  • Class[] = getClasses(); 獲取類中的內(nèi)部類

利用Java反射,修改字符串的值

早期學(xué)習(xí)String的時(shí)候,我們說字符串是不可變的,它的底層是私有的final修飾的字符數(shù)組:

private final char value[];

字符串的不可變特性體現(xiàn)在長(zhǎng)度和內(nèi)容上:

  • 長(zhǎng)度:是一個(gè)final修飾的字符數(shù)組,數(shù)組本身長(zhǎng)度不可改變,final修飾以后,它的引用不可以再指向新的對(duì)象。
  • 內(nèi)容:它是String類中的私有成員屬性,外部不可以訪問到,同時(shí)它并沒有提供共有的直接操作value[]數(shù)組的方法,所以我們?cè)赟tring類的外部,無法修改一個(gè)字符串的字面值。

但是學(xué)了反射以后,反射可以屏蔽掉private的作用,類中的所有屬性,我們都可以操作,雖然它是final修飾的,但我們可以修改value數(shù)組中存放的元素。

雖然修改私有屬性是強(qiáng)烈不推薦的,但反射確確實(shí)實(shí)可以做到:

import java.lang.reflect.Field;

public class ChangeStringValue {
	public static void main(String[] args) {
		String str = "hello";
		Class<?> clazz = String.class;
		try {
			Field field = clazz.getDeclaredField("value");
			field.setAccessible(true);
			//獲取str對(duì)象中的value數(shù)組
			char[] value = (char[])field.get(str);
			value[0] = 'w';
			value[1] = 'o';
			value[2] = 'r';
			value[3] = 'l';
			value[4] = 'd';
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(str);//world
	}
}

課后練習(xí)

1.通過反射的方式實(shí)現(xiàn)

class User{
	protected int id;//id號(hào)
	public String name; //用戶名
	private String password;//密碼
    boolean checkName(String name){//實(shí)現(xiàn)代碼}
    public User getName(String name){//實(shí)現(xiàn)代碼}
    public void doSomething(){//實(shí)現(xiàn)代碼}
    public void doSomething(String name,String password){//實(shí)現(xiàn)代碼}
    public void doSomething(int id,String name,String password){//實(shí)現(xiàn)代碼}
  }

a)查詢?cè)揢ser對(duì)象包含哪些屬性,屬性的名字,訪問修飾符等信息。 修改某個(gè)屬性的值,獲取某個(gè)屬性的值。

class User {
	protected int id;// id號(hào)
	public String name; // 用戶名
	private String password;// 密碼

	boolean checkName(String name) {// 實(shí)現(xiàn)代碼
		if("tom".equals(name) || "admin".equals(name))
			return true;
		else
			return false;
	}

	public String getName() {// 實(shí)現(xiàn)代碼
		return name;
	}
	public String toString() {
		return "id="+id+",name="+name+",password="+password;
	}

	public void doSomething() {// 實(shí)現(xiàn)代碼
		System.out.println("hello world");
	}

	public void doSomething(String name, String password) {// 實(shí)現(xiàn)代碼
		System.out.println("name="+name+",password="+password);
	}

	public void doSomething(int id, String name, String password) {// 實(shí)現(xiàn)代碼
		System.out.println("id="+id+",name="+name+",password="+password);
	}
}
public class Test1 {
	public static void main(String[] args) {
		String className = "com.briup.day17.que01.User";
		int id = 0;
		User u = null;
		try {
			Class c = Class.forName(className);
			u = (User)c.newInstance();
			Field[] fields = c.getDeclaredFields();
			for(Field f:fields) {
				int mod = f.getModifiers();
				String modifiers = Modifier.toString(mod);
				System.out.println(modifiers);
				if(Modifier.isPrivate(mod)) {
					//如果是私有屬性,把它的訪問權(quán)限設(shè)置為true
					f.setAccessible(true);
				}
				String fieldName = f.getName();
				System.out.println(fieldName);
				//給屬性賦值
				Class<?> fieldType = f.getType();
				if(fieldType == int.class) {
					//說明它是id
					f.set(u, ++id);
				}else if(fieldType == String.class){
					if("name".equals(fieldName)) {
						f.set(u, "tom"+id);
					}else if("password".equals(fieldName)) {
						f.set(u, "123"+id);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("==賦值以后的User對(duì)象==");
		System.out.println(u);
	}
}

b)查詢?cè)揢ser對(duì)象包含哪些方法,方法的名字,訪問修飾符,返回值,參數(shù)等信息。 通過反射調(diào)用某個(gè)方法。

public class Test2 {
	public static void main(String[] args) {
		//只調(diào)用了它的無參方法
		String className = "com.briup.day17.que01.User";
		User u = null;
		try {
			Class<?> c = Class.forName(className);
			u = (User)c.newInstance();
			Method[] methods = c.getDeclaredMethods();
			for(Method m:methods) {
				int mod = m.getModifiers();
				String modifiers = Modifier.toString(mod);
				System.out.println(modifiers);
				if(Modifier.isPrivate(mod)) {
					m.setAccessible(true);
				}
				Class<?> mreturnType = m.getReturnType();
				System.out.println(mreturnType.getSimpleName());
				String mName = m.getName();
				System.out.println(mName);
				Parameter[] parameters = m.getParameters();
				System.out.println(Arrays.toString(parameters));
				Object obj = null;
				if(parameters.length == 0) {
					//說明它是無參的
					if(Modifier.isStatic(mod)) {
						//靜態(tài)的
						obj = m.invoke(null);
					}else {
						obj = m.invoke(u);
					}
					System.out.println("無參方法"+mName+"執(zhí)行后的結(jié)果"+obj);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2.定義一個(gè)person類,包含name,age屬性,提供無參,全參構(gòu)造器,get/set方法,toString方法 使用反射的方式創(chuàng)建一個(gè)實(shí)例,調(diào)用構(gòu)造器初始化name,age,使用反射的方式調(diào)用setName方法對(duì)名稱進(jìn)行賦值,不使用setAge方法直接使用反射方式對(duì)age賦值

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

public class TestMain {
	public static void main(String[] args) throws Exception {
		String initName = "tom";
		Integer initAge = 18;
		String reName = "小張";
		Integer reAge = 12;
		String className = "com.briup.day17.que02.Person";
		Class<?> c = Class.forName(className);
		Class<?>[] parameterTypes = {String.class,Integer.class};
		Constructor<?> constructor = c.getConstructor(parameterTypes);
		Object[] initargs = {initName,initAge};
		Person p = (Person)constructor.newInstance(initargs);
		System.out.println("初始化后"+p);
		//使用反射的方式調(diào)用setName方法對(duì)名稱進(jìn)行賦值
		Method m = c.getDeclaredMethod("setName", String.class);
		m.invoke(p, reName);
		Field f = c.getDeclaredField("age");
		f.setAccessible(true);
		f.set(p, reAge);
		System.out.println("改值以后"+p);
	}
}

3.選做題

已有map<String,String> map = new HashMap<>();

map.put(“student”,“學(xué)生類的全路徑名”);

map.put(“teacher”,“老師類的全路徑名”);

初始化一個(gè)對(duì)象池(可選用map<String name,Object o>

? 池子:存儲(chǔ)容器。

? 根據(jù)map中的鍵創(chuàng)建對(duì)象,并放入池子中。

創(chuàng)建一個(gè)方法 可根據(jù)String name 通過反射創(chuàng)建對(duì)象。

創(chuàng)建一個(gè)方法 可根據(jù)名字從池子中取出對(duì)象。

測(cè)試:

ObjectPool pool= new ObjectPool();
pool.initPool();
System.out.println(pool.getObject("student"));
System.out.println(pool.getObject("teacher"));

import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class ObjectPool {
	private static Map<String, Object> objPool = new HashMap<>();

	public void initPool() {
		Properties prop = new Properties();
		prop.setProperty("student", "com.briup.day17.que03.Student");
		prop.setProperty("teacher", "com.briup.day17.que03.Teacher");
		FileWriter fw;
		try {
			fw = new FileWriter("./src/com/briup/day17/que03/msg.properties");
			prop.store(fw, "this is some Class msg");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(fw != null)
					fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Enumeration<?> enumeration = prop.propertyNames();
		while (enumeration.hasMoreElements()) {
			String key = (String) enumeration.nextElement();
			String value = prop.getProperty(key);
			objPool.put(key, createObj(value));
		}
	}

	// 創(chuàng)建一個(gè)方法 可根據(jù)String name 通過反射創(chuàng)建對(duì)象。
	public Object createObj(String className) {
		Class<?> c;
		Object obj = null;
		try {
			c = Class.forName(className);
			Constructor<?> constructor = c.getDeclaredConstructor();
			obj = constructor.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;
	}

	// 創(chuàng)建一個(gè)方法 可根據(jù)名字從池子中取出對(duì)象。
	public Object getObject(String name) {
		return objPool.get(name);
	}
}
public class TestMain {
	public static void main(String[] args) {
		ObjectPool pool= new ObjectPool();
		pool.initPool();
		System.out.println(pool.getObject("student"));
		System.out.println(pool.getObject("teacher"));
	}
}

到此這篇關(guān)于Java中反射reflect的基礎(chǔ)知識(shí)講解的文章就介紹到這了,更多相關(guān)Java反射reflect內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java十分鐘精通類?封裝?繼承

    Java十分鐘精通類?封裝?繼承

    基礎(chǔ)不牢地動(dòng)山搖,類、封裝、繼承是我們?cè)趯W(xué)習(xí)基礎(chǔ)時(shí)必然要碰到的知識(shí)點(diǎn),讓我們一起來學(xué)習(xí)或回顧一下,感興趣的伙伴來看看吧
    2022-03-03
  • JAVA基礎(chǔ)快速?gòu)娜腴T到精通

    JAVA基礎(chǔ)快速?gòu)娜腴T到精通

    Java是一門面向?qū)ο蟮木幊陶Z(yǔ)言,不僅吸收了C++語(yǔ)言的各種優(yōu)點(diǎn),還摒棄了C++里難以理解的多繼承、指針等概念,因此Java語(yǔ)言具有功能強(qiáng)大和簡(jiǎn)單易用兩個(gè)特征
    2022-03-03
  • SpringBoot實(shí)現(xiàn)文件壓縮處理詳解

    SpringBoot實(shí)現(xiàn)文件壓縮處理詳解

    在工作我們經(jīng)常會(huì)出現(xiàn)有多個(gè)文件,為了節(jié)省資源會(huì)將多個(gè)文件放在一起進(jìn)行壓縮處理,本文將使用SpringBoot實(shí)現(xiàn)文件壓縮處理,感興趣的可以了解下
    2024-11-11
  • 一篇文章徹底搞懂面試中常被問的各種“鎖”

    一篇文章徹底搞懂面試中常被問的各種“鎖”

    這篇文章主要給大家介紹了關(guān)于面試中常被問的各種“鎖”的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 解決idea中Terminal終端無法執(zhí)行GIT命令+Terminal 中文亂碼問題

    解決idea中Terminal終端無法執(zhí)行GIT命令+Terminal 中文亂碼問題

    這篇文章主要介紹了解決idea中Terminal終端無法執(zhí)行GIT命令+Terminal 中文亂碼問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 詳解Spring Boot Junit單元測(cè)試

    詳解Spring Boot Junit單元測(cè)試

    本篇文章主要介紹了詳解Spring Boot Junit單元測(cè)試,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Java實(shí)現(xiàn)微信紅包分配規(guī)則

    Java實(shí)現(xiàn)微信紅包分配規(guī)則

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)仿微信紅包分配規(guī)則,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 關(guān)于springboot 配置date字段返回時(shí)間戳的問題

    關(guān)于springboot 配置date字段返回時(shí)間戳的問題

    這篇文章主要介紹了springboot 配置date字段返回時(shí)間戳的問題,在springboot2.0后,spring會(huì)將Date字段自動(dòng)給轉(zhuǎn)成UTC字符串了(在沒有配置的情況下),所以date需要轉(zhuǎn)換成時(shí)間戳還是yyyy-MM-dd HH:mm:ss,具體解決方法跟隨小編一起看看吧
    2021-07-07
  • Object.wait()與Object.notify()的用法詳細(xì)解析

    Object.wait()與Object.notify()的用法詳細(xì)解析

    以下是對(duì)java中Object.wait()與Object.notify()的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下
    2013-09-09
  • 總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    總結(jié)一下Java回調(diào)機(jī)制的相關(guān)知識(shí)

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Java回調(diào)機(jī)制展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評(píng)論