黑马程序员_Java反射机制

本文深入介绍了Java反射机制的基础知识及应用场景,包括如何使用反射创建对象、访问类成员、调用方法等内容,并探讨了反射在JavaBean中的应用。

------- android培训java培训、java学习型技术博客、期待与您交流! ----------

java反射

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
也可以说是:反射就是把java类中的各种成分映射成相应的java类。

1、java类反射中所必须的类:

Field:提供有关类和接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
Constructor:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
Method:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。这个类不难理解,它是用来封装反射类方法的一个类。
Class:类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。
-----------------------------
public Field getField(String name) 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段
public Field[] getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段
public Field getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段
public Field[] getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
-----------------------------
public Method getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
--setAccessible(true);需要暴力反射才能得到私有方法
public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法
-----------------------------
public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
public Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法
public Constructor<?>[] getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。它们是公共、保护、默认(包)访问和私有构造方法
Object:每个类都使用Object作为超类。所有对象(包括数组)都实现这个类的方法。

2、新建类的实例

2.1 调用类的Class对象的newInstance方法,该方法调用对象null构造函数。
2.2 调用默认Constructor对象的newInstance方法
2.3 调用带参数Constructor对象的newInstance方法 public T newInstance(Object... initargs)

如下以Person为例:
package com.test.reflect;


public class Person {


	private int age;
	public static String animal = "高级";
	public String name;
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	private Person(){
	}
	public Person(String name){
		this.name = name;
	}
	public void sayHello(){
		System.out.println("你好!");
	}
	private void funk(){
		System.out.println("SB");
	}
	public static void search(){
		System.out.println(animal);
	}
}
构造方法的反射
Constructor类:
Class.getConstructor(参数类型);//获得构造方法(public 修饰)
newInstance(Object... obj);//同样类型的对象
反射会导致系统性能下降


成员变量的反射
Field类
Class.getField(变量名);
get(Object);//得到可见的
----------------------------------------------------------------
package com.test.reflect;


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


public class ReflectDemo {


	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		//获得Class对象
		Class clazz = Person.class;	
		try {
			clazz = Class.forName("com.test.reflect.Person");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Person p = new Person("zhangsan",13);
		clazz = p.getClass();
		//-------------------------
		//获得构造方法
		Constructor[] cons = clazz.getConstructors();
		System.out.println(cons.length);
		cons = clazz.getDeclaredConstructors();
		System.out.println(cons.length);
		Constructor con = clazz.getConstructor(String.class);
		System.out.println(con.getName());
		con = clazz.getDeclaredConstructor(null);
		System.out.println(con.getName());
		//获取属性变量
		Field f = clazz.getField("name");
		System.out.println(f.getName());
		f = clazz.getDeclaredField("age");
		System.out.println(f.getName());
		Field[] fields = clazz.getFields();
		System.out.println(fields.length);
		fields = clazz.getDeclaredFields();
		System.out.println(fields.length);
		//对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
		Method[] methods = clazz.getMethods();
		System.out.println(methods.length);
		//该对象反映此 Class 对象所表示的类或接口的指定已声明方法
		methods = clazz.getDeclaredMethods();
		System.out.println(methods.length);
		Method method = clazz.getDeclaredMethod("funk", null);
		//暴力反射
		method.setAccessible(true);
		//调用无参方法
		method.invoke(p);
		method = clazz.getMethod("search", null);
		//调用静态方法
		method.invoke(null);
	}


}
----------------------------------------------------------------
-----
暴力反射
若要通过反射调用类的私有属性和私有方法,可以在这个类私有属性和方法对应的字节码对象上,先调用setAccessible(true)来取消java语言对本私有属性和私有方法的访问检查
-----
将成员变量初值中的b换成a
Field[] fields = -字节码-.getFields();
for(Field f:fields)
{
//字节码相等用==判断
if(f.getType()==String.class){
String str = (String)f.get(-对象-);
String newS = str.replace('b','a');//存在异常
field.set(-对象-,newS);
}
}

成员方法的反射
Method类
Method mm = String.class.getMethod("charAt",int.class);
mm.invoke(str,1);//反射调用方法
如果传递给Method对象的invoke()方法的第一个参数为null,这说明Method对象对应的是一个静态方法。


使用反射方式执行某个类中的main方法。
Class clazz = Class.forName(arg[0]);
Method mainMethod = clazz.getMethod("main",String[].class);
mainMethod.invoke(null,new Object[]{new String[]{"",""}});//注意Object
mainMethod.invoke(null,(Object){new String[]{"",""}});

3、数组反射

int[] a1 = new int[3];//---Object a1对的---Object[] a1错的 
int[] a2 = new int[4];//---Object a2
int[][] a3 = new int[2][3];//---Object[] a3
String[] a4 = new String[3];//---Object[] a4

a1.getClass()==a2.getClass();//true
a1.getClass()==a3.getClass();//false
a1.getClass()==a4.getClass();//false
a1.getClass().getName();
a1.getClass().getSuperclass().getName();
Array类
Class isArray();
getLength();
get(数组对象,角标);
可以得到数组中每一个元素的类型,得不到数组的类型。

框架概念
模拟框架

用类加载器的方式管理资源和配置文件
配置文件一定要用完整路径,但完整路径不是硬编码,而是运算出来的。
--.class.getClassLoader().getResourceAsStream(包名+资源名文件);
--.class.getResourceAsStream(资源名文件或者资源子包+资源名文件);


4、JavaBean

是一个特殊的java类,
注意格式,存在getxxx/setxxx或者isxxx方法
好处:
在java ee开发中,经常要使用javabean。很多环境就要求按javabean方式进行操作,别人都这么用和要求这么做
JDK中提供了javabean进行操作的api,这套api就称为内省。用内省这套api操作javabean比用普通类的方式方便。
PropertyDescriptor类
PropertyDescriptor pd = new PropertyDescriptor(propertyName,beanClass);
简单内省操作
复制内省操作
IntroSpector类
BeanInfo类
BeanUtils工具包 apache提供
common-beanutils.jar
日志开发包
common-logging-1.x.jar
getproperties();
setproperty();
支持级联操作
JavaBean -> Map
java7新特性 Map map = {name:"zxx",age:18};
PropertyUtils类

 

------- android培训java培训、java学习型技术博客、期待与您交流! ----------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值