java基础——反射

一、获取类对象
类对象概念: 所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
1、什么是类对象
在理解类对象之前,先说我们熟悉的对象之间的区别:
garen和teemo都是Hero对象,他们的区别在于,各自有不同的名称,血量,伤害值。

然后说说类之间的区别
Hero和Item都是类,他们的区别在于有不同的方法,不同的属性。

类对象,就是用于描述这种类,都有什么属性,什么方法的

2、获取类对象
获取类对象有3种方式

  1. Class.forName
  2. Hero.class
  3. new Hero().getClass()
    在一个JVM中,一种类,只会有一个类对象存在。所以以上三种方式取出来的类对象,都是一样的。
    注: 准确的讲是一个ClassLoader下,一种类,只会有一个类对象存在。通常一个JVM下,只会有一个ClassLoader。
package reflection;

import Charactor.Hero;

public class TestReflection {

	public static void main(String[] args) {
		String className = "Charactor.Hero"; //Hero的路径
		try {
			//获取类对象的三种方法
			//方法一Class.forName(className)
			Class class1 = Class.forName(className);
			System.out.println(class1);
			//方法二Hero.class
			Class class2 = Hero.class;
			System.out.println(class2);
			//方法三new Hero().getClass()
			Class class3 = new Hero().getClass();
			System.out.println(class3);
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

}

3、获取类对象的时候,会导致类属性被初始化
为Hero增加一个静态属性,并且在静态初始化块里进行初始化
无论什么途径获取类对象,都会导致静态属性被初始化,而且只会执行一次。(除了直接使用 Class c = Hero.class 这种方式,这种方式不会导致静态属性被初始化)

package Charactor;
import java.io.Serializable;
public class Hero implements Serializable {
	public String name;
	public float hp;
    public int damage;
    public int id;
	private static final long serialVersionUID = 1L;  //表示这个类当前的版本,如果有了变化,比如新设计了属性,就应该修改这个版本号
	
	//类属性
    static String copyright;
 
    static {
        System.out.println("初始化 copyright");
        copyright = "版权由Riot Games公司所有";
    }
 

	
	public Hero(String name) {
		this.name = name;

	}
	public Hero() {
		// TODO Auto-generated constructor stub
	}
	
	public String toString() {
		return name;
	}

}

//执行后的结果
初始化 copyright
class Charactor.Hero
class Charactor.Hero
class Charactor.Hero

二、创建对象
与传统的通过new 来获取对象的方式不同
反射机制,会先拿到Hero的“类对象”,然后通过类对象获取“构造器对象”
再通过构造器对象创建一个对象

package reflection;

import java.lang.reflect.Constructor;

import Charactor.Hero;

public class TestReflection {

	public static void main(String[] args) {
		
		//传统方法
		Hero h1 = new Hero();
		h1.name = "提莫";
		System.out.println(h1);
		

		String className = "Charactor.Hero"; //Hero的路径
		try {
			//获取类对象的三种方法
			//方法一Class.forName(className)
			Class class1 = Class.forName(className);
			System.out.println(class1);
			//方法二Hero.class
			Class class2 = Hero.class;
			System.out.println(class2);
			//方法三new Hero().getClass()
			Class class3 = new Hero().getClass();
			System.out.println(class3);
			
			//使用反射的方式创建一个对象
			//构造器
			Constructor constructor = class1.getConstructor();
			//通过构造器实例化
			Hero h2 = (Hero)constructor.newInstance();
			h2.name = "盖伦";
			System.out.println(h2);
					
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

三、访问属性
通过反射机制修改对象的属性
为了访问属性,把name修改为public。
对于private修饰的成员,需要使用setAccessible(true)才能访问和修改。

getField和getDeclaredField的区别

这两个方法都是用于获取字段
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))

package reflection;

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

import Charactor.Hero;

public class TestReflection {

	public static void main(String[] args) {
		
		//传统方法
		Hero h1 = new Hero();
		h1.name = "提莫";
		System.out.println(h1);
		
		Hero h =new Hero();
        //使用传统方式修改name的值为garen
        h.name = "garen";
		System.out.println(h);

		String className = "Charactor.Hero"; //Hero的路径
		try {
			
			//获取类Hero的名字叫做name的字段
            Field f1= h.getClass().getDeclaredField("name");
            //修改这个字段的值
            f1.set(h, "teemo");
            System.out.println(h);
					
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

四、调用方法
首先为Hero的name属性,增加setter和getter
通过反射机制调用Hero的setName

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
 // 获取这个方法的名字叫做setName,参数类型是String的方法
 Method m = h.getClass().getMethod("setName", String.class);
 // 对h对象,调用这个方法
 m.invoke(h, "盖伦");
 // 使用传统的方式,调用getName方法
 System.out.println(h.getName());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值