JAva反射学習ノート

9420 ワード

なんとなく卒业して半年余り、前に勉强した论理の知识も忘れてしまったので、论理に戻ることを望んでいないようです.自分の道を続けるしかありません.何も分かりませんが、何かを书いて自分のノートにしましょう.
    最近自分でspringフレームワークを见て、springに対する理解は完全に菜鸟级ですが、javaの反射の応用を见ました.
    原理については全く知らないが、これからじっくり研究する時間があるだろう.結局、私のような菜鳥にとってはまず勉強して使えば混ぜることができる.そんなに深く蓄積してこそ見ることができるだろう.
    実行中のプログラムに対して、彼の中のクラス属性とドメイン属性を知ることができれば、それはどんなに素晴らしいことか.javaの反射はこれを実現することである.
ここには主に3つのクラスがあります.
TaskStarterがタスクをタイミングで実行

package com.maximilian.www;

import java.util.Timer;

public class TaskStarter 
{
	private static final long delayTime=1000;
	private static final long intervalTime=2000;
	private static Timer timer = new Timer();
	public static void main(String [] args)
	{
		System.out.println("start task!");
		timer.schedule(new IntervalTask(), delayTime, intervalTime);
	}
}

IntervalTask:タスク

package com.maximilian.www;

import java.util.TimerTask;
import test.ReflectionTest;

public class IntervalTask extends TimerTask
{
	public int tmpInt=0;
	public String tmpString="0";
	
	private String string1 = "1";
	private static String string2 = "2";
	public String string3 = "3";
	public static String string4 = "4";
	public IntervalTask(int argInt,String argString)
	{
		this.tmpInt=argInt;
		this.tmpString=argString;
	}
	
	@Override
    public void run()
    {
	    System.out.println("----------------"); 
	    ReflectionTest test = new ReflectionTest();
	    System.out.println(test.getObjectProperty(this, "string3"));
	    Object[] args ={1,"1"};
	    test.getAndInvokeMethod(this, null, "print1");
	    test.getAndInvokeMethod(this, args, "print5");
	    
    }
	private void print1()
	{
		System.out.println("string1:"+string1+"\r
"+"string2:"+string2+"\r
"+"string3:"+string3+"\r
"+"string4:"+string4+"\r
"); } private static void print2() { System.out.println("string2:"+string2+"\r
"+"string4:"+string4+"\r
"); } public void print3() { System.out.println("string1:"+string1+"\r
"+"string2:"+string2+"\r
"+"string3:"+string3+"\r
"+"string4:"+string4+"\r
"); } public static void print4() { System.out.println("string2:"+string2+"\r
"+"string4:"+string4+"\r
"); } public static void print5(int argInt, String argString) { System.out.println("string2:"+string2+"\r
"+"string4:"+string4+"\r
"); } public void print6(int argInt, String argString) { System.out.println("string2:"+string2+"\r
"+"string4:"+string4+"\r
"); } }

ReflectionTest:反射をテストする
主にできることは次のとおりです.
1.クラスの新規インスタンス


	    Class<?> taskClass = Class.forName("com.maximilian.www.IntervalTask");
	    Constructor<?> con = taskClass.getConstructor(new Class[]{});
	    Object obj1 = con.newInstance();
	    System.out.println(obj1.toString());
	    System.out.println("tmpInt:"+((IntervalTask)obj1).tmpInt+"  tmpString:"+((IntervalTask)obj1).tmpString);

印刷結果:com.maximilian.www.IntervalTask@12940b3
tmpInt:0  tmpString:0
上はクラスのパラメトリックを持たないコンストラクション関数であるが、もちろんパラメータ付きの異なるコンストラクション関数を呼び出すこともできる.
IntervalTaskのコンストラクション関数にpublic IntervalTask(int argInt,String argString)がある場合は、次の例を新規作成します.


	    Class<?> [] parameterTypes = {int.class,String.class};
	    Constructor<?> con2 = taskClass.getConstructor(parameterTypes);
	    Object [] paramters ={1,"1"};
	    Object obj2 = con2.newInstance(paramters);
	    System.out.println(obj2.toString());
	    System.out.println("tmpInt:"+((IntervalTask)obj2).tmpInt+"  tmpString:"+((IntervalTask)obj2).tmpString);

印刷結果:com.maximilian.www.IntervalTask@158f9d3
tmpInt:1  tmpString:1
2.クラスの静的プロパティの取得


	    Field field =taskClass.getField("string4");
Object value = field.get(taskClass);
	    System.out.println(value);

ここでは、getDeclaredFieldとgetFieldの違いは、クラスのプライベート属性を取得できることである.
プロパティの名前が不明な場合は、すべてを一度に取得できます.
    Field [] field =taskClass. getDeclaredFields();
クラス内のドメインのタイプを知らない場合は、次のことができます.
    Field field =taskClass.getField("string4");
    Class typeClass = field.getType();
    修正すると以下のようになります(ここでの修正は実行するプログラムには役に立たず、実行プログラムのクラスオブジェクトに転送してここで修正することができます).


field.setAccessible(true);
Constructor<?> constructor = typeClass.getConstructor(String.class);
	    Object object = constructor.newInstance("11");
	    field.set(taskClass,object);
	    Object value = field.get(taskClass);
	    System.out.println(value);
	    field.setAccessible(false);

3.クラスを取得するための静的メソッドの実行
privateメソッドの場合:


	    Method method = taskClass.getDeclaredMethod("print2");
	    method.setAccessible(true);
	    method.invoke(taskClass, null);
	    method.setAccessible(false);

publicメソッドの場合:


	    Method method = taskClass.getMethod("print4");
	    method.invoke(taskClass, null);

パラメータ付きメソッド呼び出しの場合


	    Class[] argclass = {int.class,String.class};
	    Object [] arg={1,"1"};
	    Method method3 = taskClass.getMethod("print5",argclass);
	    method2.invoke(taskClass, arg);

   
4.オブジェクトのプロパティを取得する


	public Object getAndChangeObjectProperty(Object obj,String fieldName)
	{
		Class<?> taskClass = obj.getClass();
		Object value = null;
		try
        {
	        Field field =taskClass.getDeclaredField(fieldName);
	        field.setAccessible(true);
	        field.set(obj, "new");
	        value = field.get(obj);
	        field.setAccessible(false);
        } catch (NoSuchFieldException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (SecurityException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalArgumentException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalAccessException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
		return value;
	}

5.あるオブジェクトを取得する方法の実行


	public void getAndInvokeMethod(Object obj,Object [] args,String methodName)
	{
		Class<?> taskClass = obj.getClass();
		Method method= null;
		try
        {
			if(args==null)
			{
				method = taskClass.getDeclaredMethod(methodName);				
			}
			else
			{
			    Class[] argclass = {int.class,String.class};
			    method = taskClass.getDeclaredMethod(methodName, argclass);
			}
	        method.setAccessible(true);
	        method.invoke(obj, args);
	        method.setAccessible(false);
        } catch (NoSuchMethodException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (SecurityException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalAccessException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (IllegalArgumentException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        } catch (InvocationTargetException e)
        {
	        // TODO Auto-generated catch block
	        e.printStackTrace();
        }
	}

test.getAndInvokeMethod(this,null,“print 1”)とtest.getAndInvokeMethod(this,args,“print 5”)には、パラメータがある場合とない場合の呼び出し方法があります.
    Javaの反射が最も大きいのは、特に実行時に上記の操作をします.上のすべてはいくつかの基本的な使い方で、反射は多くの他の使いやすい方法を提供して、例えばあるオブジェクトがクラスのオブジェクトであるかどうかを判断するisinstance;ベースクラスの属性やメソッド(クラスのclass.getSuperclass()を継承してベースクラスのclassを取得する場合、以降の操作は類似しています)などがあります.
    個人的にobject.getclassとClass.Forname(package.classname)の違いについての理解:
前者はメモリ内のクラスオブジェクトを取得し、後者はメモリ内のクラスファイルを取得しますが、最終的にはメモリ内の同じブロックのようなものが取得されます.クラスファイルにはjava仮想マシンにクラスオブジェクトがロードされるだけです.前述の例では、静的属性またはメソッドでない呼び出し可能かどうかは、特定のオブジェクトがスタック内で確立されているかどうかを決定する.