反射

       类字节码文件是在硬盘上存储的,是一个个的.class文件。我们在new一个对象时,JVM会先把字节码文件的信息读出来放到内存中,第二次用时,就不用在加载了,而是直接使用之前缓存的这个字节码信息。

       字节码的信息包括:类名、声明的方法、声明的字段等信息。在Java中“万物皆对象”,这些信息当然也需要封装一个对象,这就是Class类、Method类、Field类。

       通过Class类、Method类、Field类等等类可以得到这个类型的一些信息,甚至可以不用new关键字就创建一个实例,可以执行一个对象中的方法,设置或获取字段的值,这就是反射技术

一.Class

1.1获取class对象的三种方式

Java中有一个Class类用于代表某一个类的字节码。

Java提供了三种方式获取类的字节码

(1)forName()。forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。

(2)类名.class

(3)对象.getClass()

下边是加载类的字节码的三种方式。

/**
	 * 加载类的字节码的3种方式
	 * @throws Exception
	 * */
	public void test1() throws Exception {
		// 方式一
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		// 方式二
		Class clazz2 = Person.class;
		// 方式三
		Person p1 = new Person();
		Class clazz3 = p1.getClass();
	}

1.2 通过class类获取类型的一些信息。

    1. getName()类的名称(全名,全限定名)

    2 getSimpleName()类的的简单名称(不带包名)

    3. getModifiers(); 类的的修饰符

    4.创建对象

          无参数构造创建对象

          newInstance()

    5. 获取指定参数的构造器对象,并可以使用Constructor对象创建一个实例

          Constructor<T> getConstructor(Class<?>... parameterTypes)

下边为具体的代码

/**
	 * 通过Class对象获取类的一些信息
	 * 
	 * @throws Exception
	 * */
	private static void test2() throws Exception {

		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		// 获取类的名称
		String name = clazz1.getName();
		System.out.println(name); // 
         cn.itcast.gz.reflect.Person
		// 获取类的简单名称
		System.out.println(clazz1.getSimpleName()); // Person
		// 获取类的修饰符
		int modifiers = clazz1.getModifiers();
		System.out.println(modifiers);
		// 构建对象(默认调用无参数构造.)
		Object ins = clazz1.newInstance();
		Person p = (Person) ins;
		System.out.println(p); // cn.itcast.gz.reflect.Person@c17164
		// 获取指定参数的构造函数
		Constructor<?> con = clazz1.getConstructor(String.class, int.class);
		// 使用Constructor创建对象.
		Object p1 = con.newInstance("jack", 28);
		System.out.println(((Person) p1).getName());
	}

 1.3 通过class类获取类型中方法的信息

      1.获取公共方法包括继承的父类的方法

             getMethods()返回一个数组,元素类型是Method

       2.获取指定参数的公共方法

            getMethod("setName", String.class);

      3.获得所有的方法,包括私有

             Method[] getDeclaredMethods() 

      4.获得指定参数的方法,包括私有

              Method getDeclaredMethod(String name, Class<?>... parameterTypes)

/**
	 * 获取公有方法.
	 * @throws Exception
	 * */
	private static void test3() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		// 1.获取非私用方法(包括父类继承的方法)
		Method[] methods = clazz1.getMethods();
		System.out.println(methods.length);
		for (Method m : methods) {
			// System.out.println(m.getName());
			if ("eat".equals(m.getName())) {
                 m.invoke(clazz1.newInstance(), null);
			}
		}

	}

/**
	 * 获取指定方法签名的方法
	 * 
	 * @throws Exception
	 * */
	private static void test4() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		// 获取指定名称的函数
		Method method1 = clazz1.getMethod("eat", null);
		method1.invoke(new Person(), null);
	}
/**
	 * 获取指定方法名且有参数的方法
	 * 
	 * @throws Exception
	 * */
	private static void test5() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		Method method = clazz1.getMethod("eat", String.class);
		method.invoke(new Person(), "包子");
	}

	/**
	 * 获取指定方法名,参数列表为空的方法.
	 * 
	 * @throws Exception
	 * */
	private static void test4() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		// 获取指定名称的函数
		Method method1 = clazz1.getMethod("eat", null);
		method1.invoke(new Person(), null);
	}
/**
	 * 反射静态方法
	 * @throws Exception
	 * */
	private static void test7() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		Method method = clazz1.getMethod("play", null);
		method.invoke(null, null);
	}

	/**
	 * 访问私有方法 暴力反射
	 * @throws Exception
	 * */
	private static void test6() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		Method method = clazz1.getDeclaredMethod("movie", String.class);
		method.setAccessible(true);
		method.invoke(new Person(), "老师");
	}

1.4 通过class类获取类型中字段的信息

1.获取公共字段

   Field[] getFields() 

2.获取指定参数的公共字段

   Field getField(String name) 

3.获取所有的字段

   Field[] getDeclaredFields() 

4.获取指定参数的字段,包括私用

   Field getDeclaredField(String name) 

 

/**
	 * 获取公有的字段
	 * */
	private static void test8() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		Field[] fields = clazz1.getFields();
                Person p = new Person();
		System.out.println(fields.length);
		for (Field f : fields) {
			System.out.println(f.getName());
			if ("name".equals(f.getName())) {
				System.out.println(f.getType().getName());
				f.set(p, "jack");
			}
		}
		System.out.println(p.getName());

	}

/**
	 * 获取私有的字段
	 * @throws Exception
	 * */
	private static void test9() throws Exception {
		Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
		Field field = clazz1.getDeclaredField("age");
		System.out.println(field.getName());
		field.setAccessible(true);
		Person p = new Person();
		field.set(p, 100);
		System.out.println(p.getAge());
	}

参考自刘意java ,侵删!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值