黑马程序员--基础加强反射

---------------------- ASP.Net+Android+IOS开发.NET培训、期待与您交流! ----------------------

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

 java反射:就是把java类中的各种成分映射成相应的java类

众多的java类用什么表示呢?
Class ,每一个java类,类的名字,类属于哪个包,类的成员变量,类的方法,类的子类

如何得到各个字节码对应的实例对象(Class类型)
1>类.class 
2>对象.getClass()
3>Class的静态方法forName("类名")
Class.forName("java.lang.String")
作用:返回字节码
返回的方式:
 1>类的字节码已经加载到内存中,只有找到那份字节码返回就可以
 2>java虚拟机还没有这边字节码,用类加载器加载进来,把加载进来的字节码缓存到java虚拟机中,
 后面只要直接返回就可以


九个预定义Class实例对象

  • 八个基本类型加void.class 

构造方法的反射应用
Constructor类代表某个类中的一个构造方法
1>得到某个类所有的构造方法:
例子:Constructor[] constructor = Class.forName("java.lang.String").getConstructor();
2>得到某一个的构造方法
例子:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
3>创建实例对象
通常方式: String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstrance(new StringBuffer("abc"));
Constructor.newInstance()//可以根据传入的参数,调用任意构造构造函数
例子:
import java.lang.reflect.Constructor;

public class Reflect1
{
	public static void main(String[] args){
		try{
			Constructor constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
			String str = (String)constructor1.newInstance(new StringBuffer("abc"));
			System.out.println(str.charAt(2));
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

new和newInstance的区别
在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,
最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一个新类
从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。但是使用newInstance()方法的时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。而完成上面两个步骤的正是Class的静态方法forName()所完成的,这个静态方法调用了启动类加载器,即加载java API的那个加载器。
现在可以看出,newInstance()实际上是把new这个方式分解为两步,即首先调用Class加载方法加载某个类,然后实例化。 这样分步的好处是显而易见的。我们可以在调用class的静态加载方法forName时获得更好的灵活性,提供给了一种降耦的手段。
最后用最简单的描述来区分new关键字和newInstance()方法的区别:
newInstance: 弱类型。低效率。只能调用无参构造。 
new: 强类型。相对高效。能调用任何public构造。

通过反射创建新的类示例,有两种方式: 
Class.newInstance() 
Constructor.newInstance() 

以下对两种调用方式给以比较说明: 
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数; 
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。 
Class.newInstance() 抛出所有由被调用构造函数抛出的异常。 
Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的; 

Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。 


成员变量的反射

Filed类代表成员变量
例子:

import java.lang.reflect.*;

public class Reflect2
{
	public static void main(String[] args){
		ReflectDemo r = new ReflectDemo(3,5);
		//先得到类的字节码
		try{
			Field fieldX = r.getClass().getField("x");
			System.out.println(fieldX.get(r));
			Field fieldY = r.getClass().getField("y");
			System.out.println(fieldY.get(r));
		}catch(Exception e){
			e.printStackTrace();
		}

	}
}

class ReflectDemo
{
	public int x;
	public int y;
	public ReflectDemo(int x,int y){
		this.x = x;
		this.y = y;
	}
}

成员方法的反射
Method类代表某个类中的一个成员方法
得到类中的某一个方法
例子:
Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
         如果传递给Method对象的invoke()方法的一个参数为Null,这有着什么样的意义呢?
说明该Method对象对应的一个静态方法

例子:
import java.lang.reflect.*;

public class Test6 
{
	public static void main(String[] args) 
	{
		try{
			//反射方式创建对象
			Class c = Class.forName("ReflectDemo");
			ReflectDemo r = (ReflectDemo)c.newInstance();

			//得到方法,方法名和参数类型
			Method m = c.getMethod("print",String.class);

			//调用invoke方法,传入对象和方法类型值
			m.invoke(r,"Hello");

		}catch(Exception e){
			e.printStackTrace();
		}

	}
}

class ReflectDemo
{
	public void print(String str){
		System.out.println(str);
	}
}

综合实例:
import java.lang.reflect.*;

/**
 *第8题: 定义一个标准的JavaBean,名叫Person,包含属性name、age。
 *使用反射的方式创建一个实例、调用构造函数初始化name、age,使用反射方式调用setName方法对名称进行设置,不使用setAge方法直接使用反射方式对age赋值
 * @author Administrator
 *
 */

public class Test8 {
	public static void main(String args[]){
		try{
			Class
     
      cla = Class.forName("Person");

			//反射方式创建构造方法带参数的对象
			Constructor
     
      constructor = cla.getConstructor(String.class,int.class);

			Person p = (Person)constructor.newInstance("wh",24);

			//设置安全检查,可以访问私有构造方法
			constructor.setAccessible(true);

			System.out.println("----修改前----");

			p.showInfo();
			
			//反射方式调用方法
			Method m = cla.getMethod("setName",String.class);
			
			//重新设置name字段
			m.invoke(p,"dahai");
			
			//获取age字段
			Field fieldAge = p.getClass().getDeclaredField("age");
			
			//设置安全检查,可以访问私有成员变量
			fieldAge.setAccessible(true);
			
			//设置age字段值
			fieldAge.set(p,25);

			System.out.println("----修改后----");

			p.showInfo();

		}catch(Exception e){
			e.printStackTrace();
		}
	}

}

class Person{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return this.name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return this.age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	//显示person信息方法
	public void showInfo(){
		System.out.println("name:"+name+"\t"+"age:"+age);
	}
}






---------------------- ASP.Net+Android+IOS开发.NET培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值