程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> java反射使用詳細引見

java反射使用詳細引見

編輯:關於JAVA

java反射使用詳細引見。本站提示廣大學習愛好者:(java反射使用詳細引見)文章只能為提供參考,不一定能成為您想要的結果。以下是java反射使用詳細引見正文


本篇文章照舊采用小例子來闡明,由於我一直覺的,案例驅動是最好的,要不然只看實際的話,看了也不懂,不過建議大家在看完文章之後,在回過頭去看看實際,會有更好的了解。
上面開端注釋。
【案例1】經過一個對象取得完好的包名和類名

package Reflect;
/**
* 經過一個對象取得完好的包名和類名
* */
class Demo{
//other codes...
}

class hello{
public static void main(String[] args) {
Demo demo=new Demo();
System.out.println(demo.getClass().getName());
}
}

【運轉後果】:Reflect.Demo
添加一句:一切類的對象其實都是Class的實例。
【案例2】實例化Class類對象

package Reflect;
class Demo{
//other codes...
}

class hello{
public static void main(String[] args) {
Class<?> demo1=null;
Class<?> demo2=null;
Class<?> demo3=null;
try{
//普通盡量采用這種方式
demo1=Class.forName("Reflect.Demo");
}catch(Exception e){
e.printStackTrace();
}
demo2=new Demo().getClass();
demo3=Demo.class;

System.out.println("類稱號 "+demo1.getName());
System.out.println("類稱號 "+demo2.getName());
System.out.println("類稱號 "+demo3.getName());

}
}

【運轉後果】:
類稱號 Reflect.Demo
類稱號 Reflect.Demo
類稱號 Reflect.Demo
【案例3】經過Class實例化其他類的對象
經過無參結構實例化對象

package Reflect;
class Person{

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;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
}

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per=null;
try {
per=(Person)demo.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
per.setName("Rollen");
per.setAge(20);
System.out.println(per);
}
}

【運轉後果】:
[Rollen 20]
但是留意一下,當我們把Person中的默許的無參結構函數取消的時分,比方自己定義只定義一個有參數的結構函數之後,會呈現錯誤:
比方我定義了一個結構函數:

public Person(String name, int age) {
this.age=age;
this.name=name;
}
然後持續運轉下面的順序,會呈現:
java.lang.InstantiationException: Reflect.Person
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at Reflect.hello.main(hello.java:39)
Exception in thread "main" java.lang.NullPointerException
at Reflect.hello.main(hello.java:47)
所以大家當前再編寫運用Class實例化其他類的對象的時分,一定要自己定義無參的結構函數

【案例】經過Class調用其他類中的結構函數 (也可以經過這種方式經過Class創立其他類的對象)
[code]
package Reflect;
import java.lang.reflect.Constructor;

class Person{

public Person() {

}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString(){
return "["+this.name+" "+this.age+"]";
}
private String name;
private int age;
}

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per1=null;
Person per2=null;
Person per3=null;
Person per4=null;
//獲得全部的結構函數
Constructor<?> cons[]=demo.getConstructors();
try{
per1=(Person)cons[0].newInstance();
per2=(Person)cons[1].newInstance("Rollen");
per3=(Person)cons[2].newInstance(20);
per4=(Person)cons[3].newInstance("Rollen",20);
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per1);
System.out.println(per2);
System.out.println(per3);
System.out.println(per4);
}
}
【運轉後果】:
[null 0]
[Rollen 0]
[null 20]
[Rollen 20]
【案例】
前往一個類完成的接口:
[code]
package Reflect;

interface China{
public static final String name="Rollen";
public static int age=20;
public void sayChina();
public void sayHello(String name, int age);
}

class Person implements China{
public Person() {

}
public Person(String sex){
this.sex=sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public void sayChina(){
System.out.println("hello ,china");
}
@Override
public void sayHello(String name, int age){
System.out.println(name+" "+age);
}
private String sex;
}

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
//保管一切的接口
Class<?> intes[]=demo.getInterfaces();
for (int i = 0; i < intes.length; i++) {
System.out.println("完成的接口 "+intes[i].getName());
}
}
}

【運轉後果】:
完成的接口 Reflect.China
(留意,以下幾個例子,都會用到這個例子的Person類,所以為節省篇幅,此處不再粘貼Person的代碼局部,只粘貼主類hello的代碼)
【案例】:獲得其他類中的父類

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
//獲得父類
Class<?> temp=demo.getSuperclass();
System.out.println("承繼的父類為: "+temp.getName());
}
}

【運轉後果】
承繼的父類為: java.lang.Object
【案例】:取得其他類中的全部結構函數
這個例子需求在順序掃尾添加import java.lang.reflect.*;
然後將主類編寫為:

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Constructor<?>cons[]=demo.getConstructors();
for (int i = 0; i < cons.length; i++) {
System.out.println("結構辦法: "+cons[i]);
}
}
}

【運轉後果】:
結構辦法: public Reflect.Person()
結構辦法: public Reflect.Person(java.lang.String)
但是細心的讀者會發現,下面的結構函數沒有public 或許private這一類的修飾符
上面這個例子我們就來獲取修飾符

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Constructor<?>cons[]=demo.getConstructors();
for (int i = 0; i < cons.length; i++) {
Class<?> p[]=cons[i].getParameterTypes();
System.out.print("結構辦法: ");
int mo=cons[i].getModifiers();
System.out.print(Modifier.toString(mo)+" ");
System.out.print(cons[i].getName());
System.out.print("(");
for(int j=0;j<p.length;++j){
System.out.print(p[j].getName()+" arg"+i);
if(j<p.length-1){
System.out.print(",");
}
}
System.out.println("){}");
}
}
}

【運轉後果】:
結構辦法: public Reflect.Person(){}
結構辦法: public Reflect.Person(java.lang.String arg1){}
有時分一個辦法能夠還有異常,呵呵。上面看看:

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("Reflect.Person");
}catch (Exception e) {
e.printStackTrace();
}
Method method[]=demo.getMethods();
for(int i=0;i<method.length;++i){
Class<?> returnType=method[i].getReturnType();
Class<?> para[]=method[i].getParameterTypes();
int temp=method[i].getModifiers();
System.out.print(Modifier.toString(temp)+" ");
System.out.print(returnType.getName()+" ");
System.out.print(method[i].getName()+" ");
System.out.print("(");
for(int j=0;j<para.length;++j){
System.out.print(para[j].getName()+" "+"arg"+j);
if(j<para.length-1){
System.out.print(",");
}
}
Class<?> exce[]=method[i].getExceptionTypes();
if(exce.length>0){
System.out.print(") throws ");
for(int k=0;k<exce.length;++k){
System.out.print(exce[k].getName()+" ");
if(k<exce.length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
System.out.println();
}
}
}

【運轉後果】:
public java.lang.String getSex ()
public void setSex (java.lang.String arg0)
public void sayChina ()
public void sayHello (java.lang.String arg0,int arg1)
public final native void wait (long arg0) throws java.lang.InterruptedException
public final void wait () throws java.lang.InterruptedException
public final void wait (long arg0,int arg1) throws java.lang.InterruptedException
public boolean equals (java.lang.Object arg0)
public java.lang.String toString ()
public native int hashCode ()
public final native java.lang.Class getClass ()
public final native void notify ()
public final native void notifyAll ()
【案例】接上去讓我們獲得其他類的全部屬性吧,最後我講這些整理在一同,也就是經過class獲得一個類的全部框架

class hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("===============本類屬性========================");
// 獲得本類的全部屬性
Field[] field = demo.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 權限修飾符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 屬性類型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
System.out.println("===============完成的接口或許父類的屬性========================");
// 獲得完成的接口或許父類的屬性
Field[] filed1 = demo.getFields();
for (int j = 0; j < filed1.length; j++) {
// 權限修飾符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 屬性類型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " "
+ filed1[j].getName() + ";");
}
}
}

【運轉後果】:
===============本類屬性========================
private java.lang.String sex;
===============完成的接口或許父類的屬性========================
public static final java.lang.String name;
public static final int age;
【案例】其實還可以經過反射調用其他類中的辦法:

class hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
try{
//調用Person類中的sayChina辦法
Method method=demo.getMethod("sayChina");
method.invoke(demo.newInstance());
//調用Person的sayHello辦法
method=demo.getMethod("sayHello", String.class,int.class);
method.invoke(demo.newInstance(),"Rollen",20);

}catch (Exception e) {
e.printStackTrace();
}
}
}

【運轉後果】:
hello ,china
Rollen 20
【案例】調用其他類的set和get辦法

class hello {
public static void main(String[] args) {
Class<?> demo = null;
Object obj=null;
try {
demo = Class.forName("Reflect.Person");
} catch (Exception e) {
e.printStackTrace();
}
try{
obj=demo.newInstance();
}catch (Exception e) {
e.printStackTrace();
}
setter(obj,"Sex","男",String.class);
getter(obj,"Sex");
}

/**
* @param obj
* 操作的對象
* @param att
* 操作的屬性
* */
public static void getter(Object obj, String att) {
try {
Method method = obj.getClass().getMethod("get" + att);
System.out.println(method.invoke(obj));
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* @param obj
* 操作的對象
* @param att
* 操作的屬性
* @param value
* 設置的值
* @param type
* 參數的屬性
* */
public static void setter(Object obj, String att, Object value,
Class<?> type) {
try {
Method method = obj.getClass().getMethod("set" + att, type);
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}// end class

【運轉後果】:

【案例】經過反射操作屬性

class hello {
public static void main(String[] args) throws Exception {
Class<?> demo = null;
Object obj = null;

demo = Class.forName("Reflect.Person");
obj = demo.newInstance();

Field field = demo.getDeclaredField("sex");
field.setAccessible(true);
field.set(obj, "男");
System.out.println(field.get(obj));
}
}// end class

【案例】經過反射獲得並修正數組的信息:
[code]
import java.lang.reflect.*;
class hello{
public static void main(String[] args) {
int[] temp={1,2,3,4,5};
Class<?>demo=temp.getClass().getComponentType();
System.out.println("數組類型: "+demo.getName());
System.out.println("數組長度 "+Array.getLength(temp));
System.out.println("數組的第一個元素: "+Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修正之後數組第一個元素為: "+Array.get(temp, 0));
}
}

【運轉後果】:
數組類型: int
數組長度 5
數組的第一個元素: 1
修正之後數組第一個元素為: 100
【案例】經過反射修正數組大小

class hello{
public static void main(String[] args) {
int[] temp={1,2,3,4,5,6,7,8,9};
int[] newTemp=(int[])arrayInc(temp,15);
print(newTemp);
System.out.println("=====================");
String[] atr={"a","b","c"};
String[] str1=(String[])arrayInc(atr,8);
print(str1);
}

/**
* 修正數組大小
* */
public static Object arrayInc(Object obj,int len){
Class<?>arr=obj.getClass().getComponentType();
Object newArr=Array.newInstance(arr, len);
int co=Array.getLength(obj);
System.arraycopy(obj, 0, newArr, 0, co);
return newArr;
}
/**
* 打印
* */
public static void print(Object obj){
Class<?>c=obj.getClass();
if(!c.isArray()){
return;
}
System.out.println("數組長度為: "+Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i)+" ");
}
}
}

【運轉後果】:
數組長度為: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
數組長度為: 8
a b c null null null null null

靜態代理
【案例】首先來看看如何取得類加載器:

class test{

}
class hello{
public static void main(String[] args) {
test t=new test();
System.out.println("類加載器 "+t.getClass().getClassLoader().getClass().getName());
}
}

【順序輸入】:
類加載器 sun.misc.Launcher$AppClassLoader
其真實java中有三品種類加載器。
1)Bootstrap ClassLoader 此加載器采用c++編寫,普通開發中很少見。
2)Extension ClassLoader 用來停止擴展類的加載,普通對應的是jre\lib\ext目錄中的類
3)AppClassLoader 加載classpath指定的類,是最常用的加載器。同時也是java中默許的加載器。
假如想要完成靜態代理,首先需求定義一個InvocationHandler接口的子類,已完成代理的詳細操作。
[code]
package Reflect;
import java.lang.reflect.*;

//定義項目接口
interface Subject {
public String say(String name, int age);
}

// 定義真實項目
class RealSubject implements Subject {
@Override
public String say(String name, int age) {
return name + " " + age;
}
}

class MyInvocationHandler implements InvocationHandler {
private Object obj = null;

public Object bind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object temp = method.invoke(this.obj, args);
return temp;
}
}

class hello {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("Rollen", 20);
System.out.println(info);
}
}

【運轉後果】:
Rollen 20
類的生命周期
在一個類編譯完成之後,下一步就需求開端運用類,假如要運用一個類,一定離不開JVM。在順序執行中JVM經過裝載,鏈接,初始化這3個步驟完成。
類的裝載是經過類加載器完成的,加載器將.class文件的二進制文件裝入JVM的辦法區,並且在堆區創立描繪這個類的java.lang.Class對象。用來封裝數據。 但是同一個類只會被類裝載器裝載以前
鏈接就是把二進制數據組裝為可以運轉的形態。

鏈接分為校驗,預備,解析這3個階段
校驗普通用來確認此二進制文件能否合適以後的JVM(版本),
預備就是為靜態成員分配內存空間,。並設置默許值
解析指的是轉換常量池中的代碼作為直接援用的進程,直到一切的符號援用都可以被運轉順序運用(樹立完好的對應關系)
完成之後,類型也就完成了初始化,初始化之後類的對象就可以正常運用了,直到一個對象不再運用之後,將被渣滓回收。釋放空間。
當沒有任何援用指向Class對象時就會被卸載,完畢類的生命周期
將反射用於工廠形式
先來看看,假如不必反射的時分,的工廠形式吧:
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

/**
* @author Rollen-Holt 設計形式之 工廠形式
*/

interface fruit{
public abstract void eat();
}

class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}

class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}

// 結構工廠類
// 也就是說當前假如我們在添加其他的實例的時分只需求修正工廠類就行了

class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}

}

這樣,當我們在添加一個子類的時分,就需求修正工廠類了。假如我們添加太多的子類的時分,改的就會很多。
如今我們看看應用反射機制:

package Reflect;

interface fruit{
public abstract void eat();
}

class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}

class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}

class Factory{
public static fruit getInstance(String ClassName){
fruit f=null;
try{
f=(fruit)Class.forName(ClassName).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Reflect.Apple");
if(f!=null){
f.eat();
}
}
}

如今就算我們添加恣意多個子類的時分,工廠類就不需求修正。

下面的愛嗎雖然可以經過反射獲得接口的實例,但是需求傳入完好的包和類名。而且用戶也無法知道一個接口有多少個可以運用的子類,所以我們經過屬性文件的方式配置所需求的子類。
上面我們來看看: 結合屬性文件的工廠形式
首先創立一個fruit.properties的資源文件,
內容為:
?1
2 apple=Reflect.Apple
orange=Reflect.Orange
 然後編寫主類代碼:


package Reflect;

import java.io.*;
import java.util.*;

interface fruit{
public abstract void eat();
}

class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}

class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}

//操作屬性文件類

class init{
public static Properties getPro() throws FileNotFoundException, IOException{
Properties pro=new Properties();
File f=new File("fruit.properties");
if(f.exists()){
pro.load(new FileInputStream(f));
}else{
pro.setProperty("apple", "Reflect.Apple");
pro.setProperty("orange", "Reflect.Orange");
pro.store(new FileOutputStream(f), "FRUIT CLASS");
}
return pro;
}
}

class Factory{
public static fruit getInstance(String ClassName){
fruit f=null;
try{
f=(fruit)Class.forName(ClassName).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class hello{
public static void main(String[] a) throws FileNotFoundException, IOException{
Properties pro=init.getPro();
fruit f=Factory.getInstance(pro.getProperty("apple"));
if(f!=null){
f.eat();
}
}
}

【運轉後果】:Apple
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved