sqlite字段是否存在_学习廖雪峰的JAVA教程---反射(访问字段)
對(duì)任意的一個(gè)Object實(shí)例,只要我們獲取了它的Class,就可以獲取它的一切信息。
我們先看看如何通過(guò)Class實(shí)例獲取字段信息。Class類提供了以下幾個(gè)方法來(lái)獲取字段:
- Field getField(name):根據(jù)字段名獲取某個(gè)public的field(包括父類)
- Field getDeclaredField(name):根據(jù)字段名獲取當(dāng)前類的某個(gè)field(不包括父類)
- Field[] getFields():獲取所有public的field(包括父類)
- Field[] getDeclaredFields():獲取當(dāng)前類的所有field(不包括父類)
我們來(lái)看一下示例代碼:
// reflectionpublic class Main { public static void main(String[] args) throws Exception { Class stdClass = Student.class; // 獲取public字段"score": System.out.println(stdClass.getField("score")); // 獲取繼承的public字段"name": System.out.println(stdClass.getField("name")); // 獲取private字段"grade": System.out.println(stdClass.getDeclaredField("grade")); }}class Student extends Person { public int score; private int grade;}class Person { public String name;}上述代碼首先獲取Student的Class實(shí)例,然后,分別獲取public字段、繼承的public字段以及private字段,打印出的Field類似:
public int Student.scorepublic java.lang.String Person.nameprivate int Student.grade一個(gè)Field對(duì)象包含了一個(gè)字段的所有信息:
- getName():返回字段名稱,例如,"name";
- getType():返回字段類型,也是一個(gè)Class實(shí)例,例如,String.class;
- getModifiers():返回字段的修飾符,它是一個(gè)int,不同的bit表示不同的含義。
以String類的value字段為例,它的定義是:
public final class String { private final byte[] value;}我們用反射獲取該字段的信息,代碼如下:
Field f = String.class.getDeclaredField("value"); //返回一個(gè)Field對(duì)象(包含字段名稱、字段類型、字段修飾符)f.getName(); // "value"f.getType(); // class [B 表示byte[]類型int m = f.getModifiers();Modifier.isFinal(m); // trueModifier.isPublic(m); // falseModifier.isProtected(m); // falseModifier.isPrivate(m); // trueModifier.isStatic(m); // false獲取字段值
利用反射拿到字段的一個(gè)Field實(shí)例只是第一步,我們還可以拿到一個(gè)實(shí)例對(duì)應(yīng)的該字段的值。
例如,對(duì)于一個(gè)Person實(shí)例,我們可以先拿到name字段對(duì)應(yīng)的Field,再獲取這個(gè)實(shí)例的name字段的值:
// reflectionimport java.lang.reflect.Field;public class Main { public static void main(String[] args) throws Exception { Object p = new Person("Xiao Ming"); Class c = p.getClass(); Field f = c.getDeclaredField("name"); Object value = f.get(p); System.out.println(value); // "Xiao Ming" }}class Person { private String name; public Person(String name) { this.name = name; }}上述代碼先獲取Class實(shí)例,再獲取Field實(shí)例,然后,用Field.get(Object)獲取指定實(shí)例的指定字段的值。
運(yùn)行代碼,如果不出意外,會(huì)得到一個(gè)IllegalAccessException,這是因?yàn)閚ame被定義為一個(gè)private字段,正常情況下,Main類無(wú)法訪問(wèn)Person類的private字段。要修復(fù)錯(cuò)誤,可以將private改為public,或者,在調(diào)用Object value = f.get(p);前,先寫(xiě)一句:
f.setAccessible(true);調(diào)用Field.setAccessible(true)的意思是,別管這個(gè)字段是不是public,一律允許訪問(wèn)。
可以試著加上上述語(yǔ)句,再運(yùn)行代碼,就可以打印出private字段的值。
有童鞋會(huì)問(wèn):如果使用反射可以獲取private字段的值,那么類的封裝還有什么意義?
答案是正常情況下,我們總是通過(guò)p.name來(lái)訪問(wèn)Person的name字段,編譯器會(huì)根據(jù)public、protected和private決定是否允許訪問(wèn)字段,這樣就達(dá)到了數(shù)據(jù)封裝的目的。
而反射是一種非常規(guī)的用法,使用反射,首先代碼非常繁瑣,其次,它更多地是給工具或者底層框架來(lái)使用,目的是在不知道目標(biāo)實(shí)例任何信息的情況下,獲取特定字段的值。
此外,setAccessible(true)可能會(huì)失敗。如果JVM運(yùn)行期存在SecurityManager,那么它會(huì)根據(jù)規(guī)則進(jìn)行檢查,有可能阻止setAccessible(true)。例如,某個(gè)SecurityManager可能不允許對(duì)java和javax開(kāi)頭的package的類調(diào)用setAccessible(true),這樣可以保證JVM核心庫(kù)的安全。
設(shè)置字段值
通過(guò)Field實(shí)例既然可以獲取到指定實(shí)例的字段值,自然也可以設(shè)置字段的值。
設(shè)置字段值是通過(guò)Field.set(Object, Object)實(shí)現(xiàn)的,其中第一個(gè)Object參數(shù)是指定的實(shí)例,第二個(gè)Object參數(shù)是待修改的值。示例代碼如下:
// reflectionimport java.lang.reflect.Field;public class Main { public static void main(String[] args) throws Exception { Person p = new Person("Xiao Ming"); System.out.println(p.getName()); // "Xiao Ming" Class c = p.getClass(); Field f = c.getDeclaredField("name"); f.setAccessible(true); f.set(p, "Xiao Hong"); System.out.println(p.getName()); // "Xiao Hong" }}class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return this.name; }}運(yùn)行上述代碼,打印的name字段從Xiao Ming變成了Xiao Hong,說(shuō)明通過(guò)反射可以直接修改字段的值。
同樣的,修改非public字段,需要首先調(diào)用setAccessible(true)。
小結(jié)
Java的反射API提供的Field類封裝了字段的所有信息:
通過(guò)Class實(shí)例的方法可以獲取Field實(shí)例:getField(),getFields(),getDeclaredField(),getDeclaredFields();
通過(guò)Field實(shí)例可以獲取字段信息:getName(),getType(),getModifiers();
通過(guò)Field實(shí)例可以讀取或設(shè)置某個(gè)對(duì)象的字段,如果存在訪問(wèn)限制,要首先調(diào)用setAccessible(true)來(lái)訪問(wèn)非public字段。
通過(guò)反射讀寫(xiě)字段是一種非常規(guī)方法,它會(huì)破壞對(duì)象的封裝。
【關(guān)鍵:
】
總結(jié)
以上是生活随笔為你收集整理的sqlite字段是否存在_学习廖雪峰的JAVA教程---反射(访问字段)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ps ico插件_Photoshop 2
- 下一篇: 安装确认书模板_Aion S车讲堂 |