黑马程序员 反射

------- android培训java培训、期待与您交流! ----------

反射的基石——Class类


java程序中的各个java类属于同一类事物,描述该事物的java类名就是Classz
Class类代表java类,它的各个实例对象分别对应各个类在内存中的字节码
字节码 :一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的


类的字节码是不同的,所有他们在内存中的内容也是不一样的,这
些对象显然具有相同的类型,这个类型就是Class,
例如
人--Person

java类--Class


得到这份字节码的方式:共有三种  
  Person p1=new Person();
Class clazz1  =System.class; //用类名.class获取一个类的字节码  
Class clazz2 = p1.getClass(); //调用对象的getClass()方法可以得到  
Class clazz3 = Class.forName(“java.util.Date”); 
Class.forName()返回方式有两种,一种是曾经被加载过,缓存在java虚拟机中,直接返回,另一种java虚拟机
中还没有,类加载器加载,然后缓存在java虚拟机中,以后直接返回
九个预定义Class实例对象:8个基本的 Java 类型(boolean、byte、char、short、int、long、float 和double)和关键字void表示为Class对象。 基本类型的字节码获取方式只有一种就是类名.class。例如int.class;
void.class  
int.class==Integer.TYPE
数组类型的Class实例对象
class.isArray();
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如int[],void  


反射  

   
反射就是把Java类中的各种成分映射成相应的Java类。例如:一个Java类中用一个Class类的对象来表示,一个

类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Java类来表示,就像汽车是一个类,汽车

中的发动机,变速箱等也是一个个类。表示Java类的Class类显然要提供一系列的方式,来获得其中的变量,方

法,构造方法,修饰符,包等信息,谢谢信息就是用相应类的实例对象来表示的,它们是:Field、Method、

Contrctor、Package等等 
 

Constructor类


得到每个类的所有的构造方法:
例子:Constructor[] constructors=Class.forName("java.lang.String").getConstructors();
得到每个构造方法:
例子:Constructor[] constructor=Class.forName("java.lang.String").getConstructor(StringBuffer.class);


Field类


Field类代表某个类中的一个成员变量
得到类中的成员变量方法
Field[ ]fields =clazz.getFields()
Field [ ]fiels = clazz.getDeclaredFields()如果成员变量类型是private类型
Field field = clazz.getField("成员变量名")
Field  fiel = clazz.getDeclaredField("成员变量名")


Method类


Method类代表某一类中一个成员方法
得到类中的某一个方法
例子
Method charAtmethod=String.class.getMethod("charAt",int.class);
调用方法
charAtmethod.invoke(str.1)//str.charAt(1);


数组的反射


具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
int[ ] a1= new int[3];
intp[ ]a2=new int[4];
int[ ][ ]a3=new int[2][3];
String[ ]a4=new String[4];
Object obj1=a1;
Object obj2=a4l;
//Object[ ]obj3=a1;
Object [ ]obj4=a3;
Object[ ]obj5=a4;
以上知识点代码如下

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;




public class ReflectTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		Constructor[]constructors = Class.forName("java.lang.String").getConstructors();
		for(Constructor constructor:constructors){
			String name = constructor.getName();
			Class[] clazzs = constructor.getParameterTypes();//获取参数类型
			for(Class clazz : clazzs){
				String paramname = clazz.getName();
			    System.out.println("name"+name+" paramname "+paramname);
			    }
			System.out.println("下一个");
		}
		Constructor constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
		//String s = new String(new StringBuffer("abc"));
		String s= (String)constructor1.newInstance(new StringBuffer("abc"));
		System.out.println(s.charAt(2));
		ReflectPoint p = new ReflectPoint(2,4);
		
		
		Field fieldY = p.getClass().getField("y");//fieldY 不是对象身上的变量,而是类上的,要用它去取某个对象对应的值
		System.out.println(fieldY.get(p));
		//爆力反射,因为x是private类型,
		Field fieldX = p.getClass().getDeclaredField("x");
		fieldX.setAccessible(true);
		System.out.println(fieldX.get(p));
		changeStringValue(p);
		System.out.println(p);
		Method methodCharAt=String.class.getMethod("charAt",int.class);
		System.out.println(methodCharAt.invoke(s,1));
		
	
		Method mainMethod =TestAgruments.class.getMethod("main", String[].class);
		mainMethod.invoke(null,(Object)new String[]{"11","122","33"});
		//new Object[]{new String[]{"11","122","33"}};1.5会自动拆箱一次,所有给他家一层
		System.out.println(args[0]);
		
		String str = "abcd";
		String[]s1 =new String[]{"a","b","c"};
		printObject(str);
		printObject(s1);
	}
	
				
		
		
		
	private static void printObject(Object obj) {
		Class clazz = obj.getClass();
		if(clazz.isArray()){
			int len = Array.getLength(obj);
			for(int i=0;i<len;i++)
				System.out.println(Array.get(obj,i));//返回指定数组对象中索引组件的值。
			
		}
		else{
			System.out.println(obj);
		}
		
	}





	private static void changeStringValue(Object obj)throws Exception {
		Field []fields = obj.getClass().getFields();
		for (Field field : fields){
			if(field.getType()== String.class){
				String oldString=(String)field.get(obj);
			    String newString=oldString.replace('c', 'x');
			    field.set(obj,newString);
			    }
			else 
				System.out.println(111111);
			}
		}
}
class TestAgruments{
	public static void main(String[] args) {
		
	}
}

import java.lang.reflect.*;


public class ReflectPerson {

	/**
	 * @param args
	 */
	public static void main(String[] args)throws Exception {
		// TODO Auto-generated method stub
		Class clazz = Class.forName("Person");
		Person p = (Person)clazz.newInstance();
		Method method=clazz.getMethod("setName", String.class);
		method.invoke(p,"xxt");
	
		Method method1=clazz.getMethod("setAge", int.class);
		method1.invoke(p,21);
		System.out.println(p.toString());

	}
	
}

public 	class ReflectPoint{
    String s = "aabbcc";
	public String s1 ="cbcca";
	private int x;
	public int y;
	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public ReflectPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
		
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		final ReflectPoint other = (ReflectPoint) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	public String toString(){
		return s+";"+s1;
		}
}



框架

我做的房子卖给用户主,由用户自己安装门窗和空调,我做的房子就是框架,用户需要使用我的框架,把门插入我提供的框架中。框架与工具有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

框架要解决的核心问题

我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序,我写的框架程序怎么调用到你以后写的类(门窗)呢?
因为在写程序时无法知道要被调用的类名,所有,在程序中无法直接new某个类的实例对象,而需要用反射方式来做
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;


public class ReflectTest2 {

	/**
	 * @param args
	 */
	public static void main(String[] args)throws Exception {
		
		InputStream in = new FileInputStream("config.properties");
		Properties pro = new Properties();//Properties对象可以加载硬盘上的信息,已键值对存在
		pro.load(in);
		in.close();
		String className=pro.getProperty("className");
		Collection collection = (Collection)Class.forName(className).newInstance();//用反射方式调用无参的构造方法
		//Collection collection =new HashSet();
		ReflectPoint p1 = new ReflectPoint(2,2);
		ReflectPoint p2 = new ReflectPoint(3,3);
		ReflectPoint p3 = new ReflectPoint(4,4);
		ReflectPoint p4 = new ReflectPoint(4,4);
		collection.add(p1);
		collection.add(p2);
		collection.add(p3);
		collection.add(p4);
		System.out.println(collection.size());

	}

}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值