【Java学习笔记】初步了解反射

Class c = Class.forName("your_class_name");

1>【什么是反射】

API是这样说的:

Package java.lang.reflect
Provides classes and interfaces for obtaining reflective information about classes and objects.
See: Description

提供用于获取类和对象的反射信息的类和接口。

详见:描述


Package java.lang.reflect Description

Provides classes and interfaces for obtaining reflective information about classes and objects. Reflection allows programmatic access to information about the fields, methods and constructors of loaded classes, and the use of reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
AccessibleObject allows suppression of access checks if the necessary ReflectPermission is available.

Array provides static methods to dynamically create and access arrays.

Classes in this package, along with java.lang.Class accommodate applications such as debuggers, interpreters, object inspectors, class browsers, and services such as Object Serialization and JavaBeans that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class.

Since:
JDK1.1

提供用于获取类和对象的反射信息的类和接口。在安全的情况下,反射允许程序获取加载类的字段,方法和构造函数,以及使用反射字段,方法和构造函数进行与之对应的底层操作。

如果相应的ReflectPermission是可用的,AccessibleObject可以执行访问检查。

Array提供了静态的方法去动态的创建和接收数组。

在当前这个类以及java.lang.Class下包含的程序,比如调试器,编译器,对象检查器,类浏览器,以及对象序列化,JavaBeans等服务,都需要通过一个给定的类来访问公共成员的目标对象(基于它运行时的类)或者声明的成员。


通过了解API,简单的来说,反射就是程序在运行时能够获取自身的信息,其中包括:加载类的字段,方法和构造函数。只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。  


2>【反射的优缺点】

优点:很明显,使用反射机制可以很灵活的创建和编译代码,降低程序的冗余度。

缺点:因为反射允许获取加载类的方法,这就包括了类的私有方法,所以反射机制打破了类的封装特性。反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。


3>【反射怎么用】

给定类的名字,然后就可以通过反射机制来获得类的所有信息。

如何通过反射机制获取类呢?

【1】通过制定类名

Class c = Class.forName("PackageNmae_Your_Class_Name");//指定的类名必须完整,即包含包名

【2】每个类都有class属性

Class c = YourClass.class;//<span style="font-family: Arial, Helvetica, sans-serif;">YourClass为自定义的类</span>

3】每个对象都有getClass()方法

YourClass yc = new YourClass();
Class c = yc.getClass();


下面列举一个简单的例子,说明反射的一些基本方法

package exp;

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

/**
 * 
 * 反射机制初学-实例
 * 
 * 使用反射打印出类的基本信息
 * @author VisionDo
 *
 */
public class ReflectExp {

	public static void main(String[] args) {
		Employee e = new Employee();
		e.setNO(1001);
		e.setName("alian");
		e.setAge(23);
		e.setBaseSalary(5500);
		e.setBonus(2500);
		InitialEmployee(e);

	}
	
	
	public static void InitialEmployee(Object o){
		Class<?> c = o.getClass();
		Method[] methods = c.getMethods();//获得类中的公用(public)方法
		Field[] fileds = c.getFields();//获得类中的公用(public)字段
		Field[] allFileds = c.getDeclaredFields();//获得类中的所有的字段
		String name;
		for(Method m:methods){
			name = m.getName();
			if(name.startsWith("get")&& !name.endsWith("Class")){
				System.out.print("字段名"+name.substring(3, name.length()));
				try {
					Object value = m.invoke(o, null);//获取字段值
					System.out.println("  字段值"+value);
				} catch (Exception e) {
					e.printStackTrace();
				} 
				
			}
				
		}
		
		System.out.println("-----------------getFileds-----------------");
		for(Field f:fileds){
			System.out.print("字段修饰符:"+Modifier.toString(f.getModifiers()));
			System.out.print("\t字段类型:"+f.getType().getSimpleName());
			System.out.println("\t字段名:"+f.getName());
		}
		
		System.out.println("-----------------getDeclaredFields-----------------");
		for(Field f:allFileds){
			System.out.print("字段修饰符:"+Modifier.toString(f.getModifiers()));
			System.out.print("\t字段类型:"+f.getType().getSimpleName());
			System.out.println("\t字段名:"+f.getName());
		}
		
	}
		
}

class Employee{
	
	private int NO;//员工编号
	private String name;//姓名
	private int age;//年龄
	private int BaseSalary;//基础薪资
	private int Bonus;//奖金
	
	
	public Employee(){}

	
	
	public int getNO() {
		return NO;
	}




	public void setNO(int nO) {
		NO = nO;
	}




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




	public int getBaseSalary() {
		return BaseSalary;
	}




	public void setBaseSalary(int baseSalary) {
		BaseSalary = baseSalary;
	}




	public int getBonus() {
		return Bonus;
	}




	public void setBonus(int bonus) {
		Bonus = bonus;
	}




	@Override
	public String toString() {
		String inf =
			this.NO+","
		       +this.name+","
		       +this.age+","
		       +this.BaseSalary+""
		       +this.Bonus;
		return inf;
	}
	
	
	
}

程序运行结果




【运行结果分析】

1>可以发现,函数语句 Field[] fileds = c.getFields();执行后,filed内是空的,也就是说,getFileds()方法没有获取到Employee类的字段信息。但是,getDeclaredFileds()方法却得到了Employee类全部的字段信息。这是为什么呢?查阅API后不难发现,getFileds()方法,只能获取到公共成员,对于protect和private成员,都是无法访问的。而getDeclaredFileds()方法则获取类内所有声明的成员。

2>Method[] methods = c.getMethods()语句获取到类内的方法,并且也输出了对应的成员变量的值。需要注意的是,Employee类的方法都是public的,那么,私有方法呢?使用getMethods()后可以访问吗?

在Employee类内添加String 型成员变量PrivateStr,并增加私有方法getPrivateMotheds()

private String getPrivateMotheds(){
		this.PrivateStr = "我是私有方法!";
		return PrivateStr;
	}


程序运行结果:


可以发现,PrivateStr值没有被打印出来,这就说明的get方法没有被获取到。

对InitialEmployee函数的代码做修改:


public static void InitialEmployee(Object o){
		Class<?> c = o.getClass();
		Method[] methods = c.getDeclaredMethods();
		String name;
		for(Method m:methods){
			name = m.getName();
			if(name.startsWith("get")&& !name.endsWith("Class")){
				name = name.substring(3, name.length());
				System.out.print("字段名:"+name);
				try {
					boolean IsPrivate = Modifier.toString(m.getModifiers()).equals("private");
					if(IsPrivate)
						m.setAccessible(true);//将私有设置为可访问
					Object value = m.invoke(o, null);//获取字段值
					System.out.println("  字段值:"+value);
				} catch (Exception e) {
					e.printStackTrace();
				} 	
			}
			
		   }	
		}


程序运行结果:


可以看到,私有方法getPrivateStr()已经执行,变量PrivateStr已经被初始化“我是私有化方法。


【备注】

代码m.setAccessible(true)是将私有成员设置为可访问,否则,程序报错。

关于Invoke函数,我还不是很了解。所以程序中,说明比较少,怕误导和我一样的菜鸟了,如果有大神看到了,希望能指点,谢谢。


【总结】

今天只是对反射进行了初步学习,对反射的理解还停留在表面,明天继续深入了解一下反射的应用。个人觉得,还是要多看API,好多不懂函数都可以在API中查找到相应的使用方法。


















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值