黑马程序员——【学习笔记】反射


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


Java的反射机制是在运行状态中,对于任意一个类(class文件),都能够直到这个类的所有属性和方法;

对于任意一个对象,都能够调用它的任意一个方法和属性。

这种动态获取的信息以及动态调用对象方法的功能称为Java语言的反射。

如果我们需要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。


1 Class类

Java程序中的各个Java类属于同一类事物,秒数这类事物的java类名就是Class

问:众多的人用一个什么类概括?

答:person类

同理,问:众多的Java类可以用一个什么类概括?

答:Class类。注意这个Class是一个类,与我们平时说的class不同。


问:Person类代表人,它的实例是什么?

答:比如张三,李四,王五。。。

同理,问:Class类代表Java类,那么它的实例对象是什么?

答:Class类的实例对象,就是对应各个类在内存中的字节码。例如,Person类的字节码,ArrayList类的字节码,等等。

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码。

不同的类的字节码是不同的。所以他们在内存中的内容是不同的。这一个个的空间可分别用一个个的对象来表示。


假设现在有一Person类,

当我们建立Class c1 = 的时候,首先要从硬盘上这个类的二进制代码(字节码)编译后加载到内存中,再用这个字节码去复制一个一个的对象。

每一份字节码就是一个Class的实例对象,即一个我们平时说的类。


2 Class类实例的创建。(即获得一个类的字节码)

①Class类的实例不用new来创建,直接用名字。

如:Class c = Person.class

②getClass()方法

如:Person p = new Person();

Class c = p.getClass();

③Class.forName("一个类的完整名称")

如:Class c=Class.forName("java.lang.String")

这个方法的实现获得字节码的途径有两个:

——这份字节码曾经被加载过,已经在加载器里,直接返回

——加载器里还没有这份字节码,就让加载器去加载,把加载进来的字节码缓存在虚拟机里,以后要得到这份字节码就不用加载了。

PS:三个方法都可以用,但在反射中更多地使用方法③。因为写源程序的时候我们还不知道未来调用者建立的这个类的名字是什么,

在运行的时候机器传出一个字符串,这个字符串包含类的名字。用变量记录这个配置文件的类的名字,传入forName();,从而操作类及其对象。

而在方法①和②中,写源程序的时候需要类名已知。

class Day27{
	public static void main(String[] args) throws Exception {
		
		//方法一
		Class c1 = Person.class;
		System.out.println(c1);
		
		//方法二
		Person p = new Person();
		Class c2 = p.getClass();
		System.out.println(c2);
		
		//方法三
		String s = "demo.Person";
		Class c3 = Class.forName(s);
		System.out.println(c3);

	}
}
class Person{
	//...
}

class demo.Person
class demo.Person
class demo.P
erson


2.1 八个基本数字类型及void的Class实例对象

boolean Boolean.TYPE;

byte Byte.TYPE;

char Character.TYPE;

short Short.TYPE;

int Integer.TYPE;

long Long.TYPE;

float Float.TYPE;

double Double.TYPE;

void Void.TYPE;


用isPrimitive方法可以判断是否基本类型

八个基本数据类不能getClass()来获得类型;,而他们的包装类可以。比如Integer


3 Class对象的应用

反射就是IBAJava类中的各种成分映射成相应的java类。

例如,一个java类中用给一个Class的对象来表示,这个java类中的组成部分:成员变量,方法,构造方法,包等信息也能用一个个java类来表示。

就像汽车,汽车本身属于一个类,而汽车里的发动机也属于一个类,汽车里的变速箱也属于一个类。。。等等。

java的成员变量,方法,构造方法,包的信息的类为:Field,Method,Constructor,Package


3.1 Constructor类

得到某个类上所有的构造方法。

Constructors[] constructor = Class.forName("java.lang.String").getConstructors();

得到某个构造方法。

Constructor cons = Class.forName().getConstructor(参数类的类型,如int.TYPE)

public class Day27 {
	public static void main(String[] args) throws Exception {
		
		Constructor stringCons=String.class.getConstructor(StringBuffer.class);//获得String中包含StringBuffer.class类为参数的构造方法
		System.out.println(stringCons);
		String s = (String) stringCons.newInstance(new StringBuffer("abc"));;//用这个构造方法创建实例
		System.out.println(s.charAt(2));
		
	}
public java.lang.String(java.lang.StringBuffer)
abc

3.2 Field类

得到某个类的某个成员

Field field = Class.forName("java.lang.String").getField(成员名字)。只能获取public的字段,private收不到

得到某个类的某个成员,包括private成员

Field field = Class.forName("java.lang.String").getDeclaredField(成员名字)。可以获取包括private的成员

取得私有成员后,还可以对其的访问取消权限检查,暴力访问

field.setAccessible(true)

获取该成员在某个具体实例对象中的值

field.get(obj);但是不能访问private的类,尽管用DeclaredField得知了这个成员。除非setAccessible(true);

对某个具体实例对象的成员赋值

field.set(obj, value);

获得某个成员所装载的类型

getType();这个是获得该成员的类型,注意与getClass()的区别。


3.3 Method类

返回Method类的数组,将其打印可获得该类所有的方法名,及其限制符,返回类型以及抛出的异常。只能返回public的成员方法

Method[] getMethods();

返回某个Method类的对象

Metood getMethod("方法名字“,参数类型);

运行得到的这个方法

invoke("对象”,参数);

public class Day27 {
	public static void main(String[] args) throws Exception {
		
		String className = "demo.Person"; 
		
		Class c = Class.forName(className);
		
		getConstructor_1(c);
		getMethod(c);

	}
	//根据空参数的构造方法创建对象
	public static void getConstructor_1(Class c) throws Exception{
		
		Object obj = c.newInstance();
		
		System.out.println(obj);
	}
	
	//返回这个类的方法
	public static void getMethod(Class c) throws Exception{
		
		Method[] methods = c.getMethods();
		
		for(Method m :methods)
			System.out.println(m);
	}
}
class Person{
	
	private String name;
	private int age;
	private int high;
	
	Person(){System.out.println("Person runs");}
	Person(String name,int age,int high){
		this.name=name;
		this.age=age;
		this.high=high;
	}
	public static void say(){
		System.out.println("Person say hi to everyone");
	}
	public void talk(){
		System.out.println("Person talk to you");
	}
}

返回如下:

Person runs
demo.Person@659e0bfd
public void demo.Person.talk()
public static void demo.Person.say()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值