黑马程序员_反射

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


一    反射的基石:Class类
1 Class类:描述java程序中的java类。例如:描述人这类事物用Person类。描述java中的类就用Class类。
(1)该类所描述的是类所属的包,该类实现的接口,该类中定义的成员等等,都可以通过Class类得到。
(2)Class类的实例对象是字节码文件对象。
(3)什么是字节码文件对象呢。当我们使用到某个类时,会从硬盘上将类编译成class文件的字节码,将字节码加载进内存在创建出一个个的实例对象。
(4)那么获取字节码实例对象有三种方式
第一种: Class cls1=类名.class
第一种: Class cls2=对象.getClass()
第一种: Class cls3=Class.forName(类的完整名字)

2 九个预定义的实例对象
基本数据类型boolean、byte、char、short、int、long、float、double和关键字 void 也表示为 Class 对象。只要源代码使用到对应的数据类型,内存就会产生对应的字节码示例对象。
int.class==Integer_TYPE;
 
3 例子:

class  ClassDemo
{
	public static void main(String[] args) throws Exception
	{
		//创建String类对象
		String s="aaa";
		//获取String类的字节码
		Class cls1=String.class;
		Class cls2=s.getClass();
		Class cls3=Class.forName("java.lang.String");
		//判断是否是同一个字节码
		System.out.println(cls1==cls2);//结果为true
		System.out.println(cls1==cls3);//结果为true
		//判断String类是不是原始类型
		System.out.println(cls1.isPrimitive());//结果为false
		//判断int类是不是原始类型
		System.out.println(int.class.isPrimitive());//结果为true
	}
}



二    反射
1 概念:反射就是把java类中的各个成分映射成java类。
  例如:java类中有成员函数,成员方法,构造函数。通过Class类可以获得这些信息。他们的类型分别是Field,Method,Constructor,他们也是java类。

2 Constructor类,用于描述类中的构造方法。可以通过Constructor类创建实例对象
(1)获取构造方法的方式:
第一:Class类对象.getConstructors();//获取某个类的全部构造方法,返回Constructor[]数组
第二:Class类对象.getConstructors(Class<?>... parameterTypes);//获取某个类的一个构造方法,而具体是哪个要看构造方法对应的参数列表

3 通过获取构造方法可以创建对应的实例对象
方法:Constructor的实例对象.newIntance(Object... initargs);//需要对返回类型进行强转

4 例子:

import java.lang.reflect.*;
class ConstructorDemo 
{
	public static void main(String[] args) throws Exception
	{
		//获取Person类的字节码对象
		Class cls1=Person.class;
		//获取Person类的全部构造方法
		Constructor[] cons=cls1.getConstructors();
		System.out.println(cons.length);//获取构造方法数量
		//获取Person中的某个构造方法
		Constructor con=cls1.getConstructor(String.class,int.class);
		//通过构造方法创建实例对象
		Person p1=(Person)con.newInstance("zhangsan",15);
		//用创建的实例对象调用方法
		System.out.println(p1.name+":"+p1.age);
	}
}

class Person
{
	String name;
	int age;
	public Person(){}
	public Person(String name)
	{
		this.name=name;
	}
	public Person(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
}

5 Field类,用于描述类中的成员变量

(1)获取类中的某个成员变量的Constructor对象用getField(String name),此方法不能获取私有的变量
(2)获取类中私有的变量的Constructor对象用getDeclaredField(String name);
(3)例子:

import java.lang.reflect.*;
class  FieldDemo
{
	public static void main(String[] args) throws Exception
	{
		//创建学生对象
		Student s=new Student("lisi",25);
		//获取学生类字节码对象
		Class cls1=s.getClass();
		//获取学生类的某个成员变量
		Field fieldName=cls1.getField("name");
		//获取某个学生对象的成员变量的值
		String s_name=(String)fieldName.get(s);
		System.out.println(s_name);

		//获取学生类中的私有成员变量
		Field fieldAge=cls1.getDeclaredField("age");
		//将私有变量设置为可访问的
		fieldAge.setAccessible(true);
		//获取s学生对象的age值
		int s_age=(int)fieldAge.get(s);
		System.out.println(s_age);
	}
}

class Student
{
	public String name;
	private int age;
	public Student(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
}

(4) Field类反射练习:

//将一个java类中的String类型的成员变量中的值的字母改掉
/*
思想:
1 获取类中所有的成员变量的Field对象数组
2 遍历Field数组并判断类型
3 如果是String类型的就获取他的值并将对应的字母换成指定的字母
*/
import java.lang.reflect.*;
class FieldTest 
{
	public static void main(String[] args) throws Exception
	{
		//创建男人对象
		Man m=new Man();
		//获取Man类的字节码对象
		Class cls1=m.getClass();
		//获取类中成员变量的Field数组
		Field[] fields=cls1.getFields();
		System.out.println(fields.length);
		//遍历数组
		for(Field field:fields)
		{
			//判断成员变量所属的类型
			if (field.getType()==String.class)
			{
				//获取变量的值
				String oldVal=(String)field.get(m);
				//将变量的值改掉
				String newVal=oldVal.replace('n','m');
				//将m对象变量上此 Field 对象表示的字段设置为指定的新值
				field.set(m,newVal);
			}
		}
		System.out.println(m.toString());

	}
}
class Man
{
	public String name="nanren";
	public int age=20;
	public String id="work000";
	public String sex="man";
	public String toString()
	{
		return name+":"+id+":"+sex;
	}
}

6 Method类,用于描述类中的成员函数

(1)例子:

//用反射的方法调用Person类中的getName()方法
import java.lang.reflect.*;
class MethodDemo 
{
	public static void main(String[] args) throws Exception
	{
		//创建人对象
		Person p=new Person();
		//获取Person字节码对象
		Class cls1=p.getClass();
		//获取Person类中的setName()方法Method对象
		Method method_setName=cls1.getMethod("setName",String.class);
		//调用setName()方法
		method_setName.invoke(p,"lisi");
		//获取Person类中的getName()方法Method对象
		Method method_getName=cls1.getMethod("getName");
		//调用Method类的getName()方法
		String name=(String)method_getName.invoke(p);
		System.out.println(name);
	}
}

class Person
{
	private String name;
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name=name;
	}
}

7 数组的反射
(1)具有相同维数和数据类型的数组具有相同的Class字节码实例对象。
(2)基本数据类型的一位数据可以被当作Object使用,不可以被当作Object[]使用。引用数据类型的一维数组可以被当作Object使用也可以被当作Object[]使用。
(3)例子:

import java.lang.reflect.*;
class ArrayDemo 
{
	public static void main(String[] args) 
	{
		int[] arr1=new int[]{1,2,3};
		int[] arr2=new int[2];
		String[] arr3=new String[3];
		int[][] arr4=new int[2][3];
		//分别获取数组的Class字节码对象
		Class cls1=arr1.getClass();
		Class cls2=arr2.getClass();
		Class cls3=arr3.getClass();
		Class cls4=arr4.getClass();
		System.out.println(cls1==cls2);//true
		System.out.println(cls1==cls3);//flase
		System.out.println(cls1==cls4);//false	
		//结论:只有维数和数据类型一致,对应的字节码对象是同一份

		//获取父类
		System.out.println(cls1.getSuperclass().getName());//返回java.lang.Object
		System.out.println(cls3.getSuperclass().getName());//返回java.lang.Object

		//调用方法打印对象
		print(arr1);
		
	}
	//定义方法用反射打印对象
	public static void print(Object obj)
	{
		//获取Object的字节码对象
		Class cls=obj.getClass();
		//判断是不是数组
		if(cls.isArray())
		{
			//遍历数组并打印
			for(int x=0;x<Array.getLength(obj);x++)
			{
				System.out.println(Array.get(obj,x));
			}
		}
		else
			System.out.println(obj);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值