Java学习笔记---Reflect

JAVA类加载和反射介绍


注意:以下代码调试版本 JDK1.6.

简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息.
反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。

当程序主动使用某个类时,若该类还没加载到内存中,系统会通过加载,链接,初始化3个操作对类进行初始化。
类字面常量”,class”创建Class对象的引用时,不会自动地初始化该Class对象,准备工作包含3个步骤:
1.加载:由类加载器执行,该步骤查找字节码,并从这些字节码中创建一个Class对象
2.链接:在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。
3.初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块

类的初始化时机
1.创建类的实例
2.访问类或接口的静态变量(static final常量除外,static final变量可以)
3.调用类的静态方法
4.反射(Class.forName(packageName.className))
5.初始化类的子类(子类初始化问题:满足主动调用,即访问子类中的静态变量、方法,否则仅父类初始化)
6.java虚拟机启动时被标明为启动类的类
注:加载顺序:启动类的static block最先加载

JAVA中获取Class对象有3种方式:
1.Class.forName()
2.Object.getClass()
3.类字面常量 xx.class

代码例子:

package ReflactTest;

class Demo 
{
	// other codes...
}

public class Test2 
{
	public static void main(String[] args)
	{
        Class<?> demo1=null;
        Class<?> demo2=null;
        Class<?> demo3=null;
        try
        {
            //一般尽量采用这种形式
            demo1=Class.forName("ReflactTest.Demo");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        demo2=new Demo().getClass();
        demo3=Demo.class;
         
        System.out.println("类名称   "+demo1.getName());//Reflect.Demo
        System.out.println("类名称   "+demo2.getName());//Reflect.Demo
        System.out.println("类名称   "+demo3.getName());//Reflect.Demo        
    }
}

执行结果:

从Class中获取信息(可以查看Class的API文档了解):

获取类的构造器 
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器

获取类的成员变量 
成员变量用Field类进行封装,主要的方法非常的类似:
public Field getDeclaredField(String name) 获取任意指定名字的成员
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量

获取类的方法 
public Method[] getMethods() 获取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合 
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法

package ReflactTest;

import java.lang.reflect.*;
import java.lang.annotation.*;

public class ClassTest
{
	// 为该类定义一个私有的构造器
	private ClassTest()
	{
	}

	// 定义一个有参数的构造器
	public ClassTest(String name)
	{
		System.out.println("执行有参数的构造器");
	}

	// 定义一个无参数的info方法
	public void info()
	{
		System.out.println("执行无参数的info方法");
	}

	// 定义一个有参数的info方法
	public void info(String str)
	{
		System.out.println("执行有参数的info方法" + ",其实str参数值:" + str);
	}

	// 定义一个测试用的内部类
	class Inner
	{
	}

	public static void main(String[] args) throws Exception
	{
		// 下面代码可以获取ClassTest对应的Class
		Class<ClassTest> clazz = ClassTest.class;

		System.out.println("输出所有构造器:");
		Constructor[] ctors = clazz.getDeclaredConstructors();
		for (Constructor c : ctors)
		{
			System.out.println(c);
		}

		System.out.println("输出所有publicc构造器:");
		Constructor[] publicCtors = clazz.getConstructors();
		for (Constructor c : publicCtors)
		{
			System.out.println(c);
		}

		System.out.println("输出所有public 方法:");
		// 获取该Class对象所对应类的全部public方法
		Method[] mtds = clazz.getMethods();
		System.out.println("ClassTest的全部public方法如下:");
		for (Method md : mtds)
		{
			System.out.println(md);
		}
		
		System.out.println("ClassTest里带一个字符串参数的info方法为:"
				+ clazz.getMethod("info", String.class));

		System.out.println("ClassTest的全部内部类如下:");
		Class<?> [] inners = clazz.getDeclaredClasses();
		for (Class c : inners)
		{
			System.out.println(c);
		}

		Class inClazz = Class.forName("ReflactTest.ClassTest$Inner");

		System.out.println("inClazz对应类的外部类为:" + inClazz.getDeclaringClass());
		System.out.println("ClassTest的包为:" + clazz.getPackage());
		System.out.println("ClassTest的父类为:" + clazz.getSuperclass());
	}
}

修改了原作者错误:forName构建内部类时应该是Class inClazz = Class.forName("ReflactTest.ClassTest$Inner");

执行结果


通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

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);//[null  0]
        System.out.println(per2);//[Rollen  0]
        System.out.println(per3);//[null  20]
        System.out.println(per4);//[Rollen  20]
    }
}

执行结果:


==========================================================

package ReflactTest;

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

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;
	}

	public void sayChina()
	{
		System.out.println("hello ,china");
	}

	public void sayHello(String name, int age)
	{
		System.out.println(name + "  " + age);
	}

	private String sex;
}

class Test3
{
	public static void main(String[] args) throws SecurityException,
			NoSuchFieldException, IllegalArgumentException,
			IllegalAccessException
	{
		Class<?> demo = null;
		try
		{
			demo = Class.forName("ReflactTest.Person");
		} catch (Exception e)
		{
			e.printStackTrace();
		}

		// 保存所有的接口
		System.out.println("--------------实现的接口----------");
		Class<?> intes[] = demo.getInterfaces();
		for (int i = 0; i < intes.length; i++)
		{
			System.out.println( intes[i].getName());
			// Reflect.China
		}

		System.out.println("--------------实现的构造方法----------");
		Constructor<?> cons[] = demo.getConstructors();
		for (int i = 0; i < cons.length; i++)
		{
			System.out.println( cons[i]);
		}

		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("){}");
		}
		try
		{
			// 调用Person类中的sayChina方法
			Method method = demo.getMethod("sayChina");
			method.invoke(demo.newInstance());// hello ,china
			// 调用Person的sayHello方法
			method = demo.getMethod("sayHello", String.class, int.class);
			method.invoke(demo.newInstance(), "Rollen", 20);// Rollen 20

		} 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() + ";");
			// private java.lang.String sex;
		}
		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() + ";");
		}
		// public static final java.lang.String name;
		// public static final int age;

		Object obj = null;
		try
		{
			obj = demo.newInstance();
		} catch (Exception e)
		{
			e.printStackTrace();
		}

		// 通过反射操作属性
		Field field1 = demo.getDeclaredField("sex");
		field1.setAccessible(true);
		field1.set(obj, "男");

		// 通过反射取得并修改数组的信息:
		int[] temp = { 1, 2, 3, 4, 5 };
		Class<?> demo1 = temp.getClass().getComponentType();
		System.out.println("数组类型: " + demo1.getName());// int
		System.out.println("数组长度  " + Array.getLength(temp));// 5
		System.out.println("数组的第一个元素: " + Array.get(temp, 0));// 1
		Array.set(temp, 0, 100);
		System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));// 100
	}
}


将反射用于工厂模式(结合属性文件的工厂模式):

首先创建一个fruit.properties的资源文件,内容为:
apple=Reflect.Apple
orange=Reflect.Orange

主类代码:

<pre name="code" class="java">package ReflactTest;

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", "ReflactTest.Apple");
			pro.setProperty("orange", "ReflactTest.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 Test4
{
	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
		}
	}
}


 
  
运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值