类反射(1)初识类反射

什么是类反射

☆什么是反射

       JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

       反射(Reflection)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查, 也称自审,并能直接操作程序的内部属性。例如,使用它能获得Java类中各成员的名称并显示出来。

       Java的这一能力在实际应用中应用得很多,在其它的程序语言中根本就不存在这一特性。例如,Pascal、C或者C++中就没有办法在程序中获得函数定义相关的信息。

       JavaBean是类反射的实际应用之一,它能让一些工具可视化的操作软件组件。这些工具通过类反射动态的载入并取得Java组件(类)的属性。后面学习的各种框架,基本上都会有反射的使用。

☆反射引例(HelloWorld、USB)

HelloWorld:

初识类反射,通过Class.forName("类名")获得一个Class对象,通过这个对象获得成员变量,构造方法和普通方法。

 

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
	public static void main(String[] args) {
		//UserModel user = new UserModel();
		try {
			Class c = Class.forName("cn.hncu.reflect.UserModel");
			//c.getFields()
			//c.getConstructors();
			//Method ms[] = c.getMethods();
			Method ms[] = c.getDeclaredMethods();
			for(int i=0;i<ms.length;i++){
				System.out.println(ms[i].toString());
			}
			
			System.out.println("-------------");
			Constructor cons[] = c.getConstructors();
			for(Constructor con: cons){
				System.out.println(con.toString());
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}
</span>

USB:

通过Usb.config配置文件和类反射来实现不用修改源代码就可以更改用的类。

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect.usb;

public interface USB {
  public abstract void work();
}
</span>


 

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect.usb;

import java.util.Properties;

public class USBFactory {
	public static USB getUSB() {
		// return new UsbOne();
		USB u = null;
		Properties p = new Properties();
		try {
			p.load(USBFactory.class.getResourceAsStream("usb.config"));
			String name = p.getProperty("name");
			Class c = Class.forName(name);
			u= (USB) c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return u;
	}
}
</span>


 

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect.usb;

public class UsbOne implements USB {
	@Override
	public void work() {
		System.out.println("UsbOne is working....");
	}
}
</span>


 

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect.usb;

public class UsbTwo implements USB {
	@Override
	public void work() {
		System.out.println("UsbTwo is working....");
	}
}
</span>

usb.config的内容如图所示:

如果想让UsbTwo工作,只需把UsbOne改成UbsTwo即可,此方法灵活且符合了Java中“开闭原则”。

反射最大的好处是解耦

反射使用的三个步骤

用于反射的类,如Method,可以在java.lang.reflect包中找到。使用这些类的时候必须要遵循三个步骤:

       第一步:获得你想操作的类的java.lang.Class对象。在运行中的Java程序中,用java.lang.Class类来描述类和接口等。

       第二步:调用诸如getDeclaredMethods的方法,取得该类中定义的所有方法的列表。

       第三步:使用反射的API来操作这些信息。

如下面这段代码:

         Class c = Class.forName("java.lang.String");

         Method ms[] = c.getDeclaredMethods();

         System.out.println(ms[0].toString());

它将以文本方式打印出String中定义的第一个方法的原型。

☆反射示例(模拟instanceof的功能)

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

public class SimulateInstanceof {

	public static void main(String[] args) {
		try {
			Class c = Class.forName("cn.hncu.reflect.UserModel");
			//boolean boo = c.isInstance( new Integer(30) ); //false
			//boolean boo = c.isInstance( new String("abc") ); //false
			boolean boo = c.isInstance( new UserModel() ); //true
			System.out.println(boo);
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}
</span>


 

获取Class对象的三种方式

★ 方式一

      通过对象的getClass方法进行获取。这种方式需要具体的类和该类的对象,以及调用getClass方法。

★ 方式二

     任何数据类型(包括基本数据类型)都具备着一个静态的属性class,通过它可直接获取到该类型对应的Class对象。这种方式要使用具体的类,然后调用类中的静态属性class完成,无需调用方法,性能更好。

★ 方式三

     通过Class.forName()方法获取。这种方式仅需使用类名,就可以获取该类的Class对象,更有利于扩展。

具体代码:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

import org.junit.Test;

//获取Class对象的三种方式
public class ReflectGetClass {

	@Test//法1:通过 对象.getClass()
	public void getClass1() {
        Person p = new Person("Jack",22);
        Class c = p.getClass();
        System.out.println(c);
	}
	
	@Test//法2:通过类型---任何数据类型(包含基本数据类型)都拥有一个静态变量class
	public void getClass2() {
		Class c = Person.class;
		System.out.println(c);
		
		Class c2 = int.class;
		System.out.println(c2);
	}
	
	@Test//法3:通过Class.forName直接获取---不依赖具体的类或对象(仅仅依赖String类,而我们做项目时通常把使用API中的类看成不是依赖的!)
	public void getClass3() {
		try {
			Class c = Class.forName("cn.hncu.reflect.Person");//“类全名”的字符串形式
			System.out.println(c);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	
	//※法3是不依赖于被反射类或对象的,能够完全达到解藕的效果,是我们以后开发当中的首选策略
	
}
</span>


 

类的解剖(获取类的定义信息)

★ 获取类的方法    

找出一个类中定义了些什么方法,这是一个非常有价值也非常基础的反射用法。

★ 获取类的构造器

找出一个类中定义的构造方法,构造器没有返回类型。

★ 获取类的属性字段

找出一个类中定义了哪些属性字段。

代码实现:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

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

import org.junit.Test;

//类的解剖:把一个类中的所有方法、属性、构造方法全部获取出来
public class ReflectDecompose {
    private static final String className="cn.hncu.reflect.Student"; 
	//private static final String className="cn.hncu.reflect.Person"; 
	
	//1 c.getMethods()----获取的是当前类及其父类的公开方法---无法获取到私有方法
	//2 c.getDeclaredMethods()----获取的是当前类自己定义的那些方法---包括私有的 但不包括父类中的方法
	@Test//获取方法
	public void fetchMethods() throws Exception{
	   Class c = Class.forName(className);
	   //Method ms[] = c.getMethods();//所能访问的方法和一个“Person p=new Person()”中的p对象一样
	   Method ms[] = c.getDeclaredMethods();
	   
	   for(int i=0;i<ms.length;i++){
		   Method m = ms[i];
		   System.out.println("name: "+m.getName());
		   System.out.println("declaringClass: "+ m.getDeclaringClass());
		   Class paramTypes[] = m.getParameterTypes();
		   for(int j=0;j<paramTypes.length;j++){
			   System.out.println("param#"+j+": "+ paramTypes[j]);
		   }
		   
		   Class returnType = m.getReturnType();
		   System.out.println("returnType: "+returnType);
		   
		   Class excepts[] = m.getExceptionTypes();
		   for(int j=0;j<excepts.length;j++){
			   System.out.println("excepts#"+j+": "+ excepts[j]);
		   }
		   
		   int modifiers = m.getModifiers();
		   System.out.println("modifiers: "+modifiers);
		   System.out.println("--------------");
	   }
	   
    }
	
	//注意,构造方法都不包含父类的
	//1 c.getConstructors()----获取的是当前类(注意不包含父类的)的公开构造方法---无法获取到私有方法
	//2 c.getDeclaredConstructors()----获取的是当前类自己定义的构造方法---包括私有的
	@Test//获取方法
	public void fetchConstructors() throws Exception{
		Class c = Class.forName(className);
		//Constructor cons[] = c.getConstructors();//所能访问的方法和一个“Person p=new Person()”中的p对象一样
		Constructor cons[] = c.getDeclaredConstructors();
		for(int i=0;i<cons.length;i++){
			Constructor con = cons[i];
			System.out.println("name: "+con.getName());
			System.out.println("declaringClass: "+ con.getDeclaringClass());
			Class paramTypes[] = con.getParameterTypes();
			for(int j=0;j<paramTypes.length;j++){
				System.out.println("param#"+j+": "+ paramTypes[j]);
			}
			
			Class excepts[] = con.getExceptionTypes();
			for(int j=0;j<excepts.length;j++){
				System.out.println("excepts#"+j+": "+ excepts[j]);
			}
			
			int modifiers = con.getModifiers();
			System.out.println("modifiers: "+modifiers);
			System.out.println("--------------");
		}
	}
	
	
	//1 c.getFields()----获取的是当前类和父类的公开属性---无法获取到私有属性
	//2 c.getDeclaredFields()----获取的是当前类自己定义的属性---包括私有的
	@Test//获取方法
	public void fetchFields() throws Exception{
		Class c = Class.forName(className);
		//Field flds[] = c.getFields();
		Field flds[] = c.getDeclaredFields();
		for(int i=0;i<flds.length;i++){
			Field fld = flds[i];
			System.out.println("name: "+fld.getName());
			System.out.println("declaringClass: "+ fld.getDeclaringClass());
			
			Class type = fld.getType();
			System.out.println("type: "+ type);
			int modifiers = fld.getModifiers();
			System.out.println("modifiers: "+Modifier.toString(modifiers) );
			System.out.println("--------------");
		}
	}
	
	
	
	
}
</span>


Student类:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

public class Student extends Person{
	public int a;
	private String spec;
   public Student(){
   }
}
</span>


Person类:

<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.reflect;

public class Person {
	private String name;
	private int age;
	public static final double PI=3.14;
	
	public Person() {
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	private Person(String name) {
		this.name = name;
	}

	private int sum( int n){
		int s=0;
		for(int i=1;i<=n;i++){
			s +=i;
		}
		return s;
	}
	
	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 name + ", " + age;
	}

}
</span>


 



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值