j2ee反射机制高级应用-基本操作

2018-12-09

反射概述

  • java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用它的任意一个方法和属性。
  • 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
  • 要想解剖一个类,必须先要获取到该类的字节码文件对象
  • 而解剖使用的就是Class类中的方法,所以要先获取到每一个字节码文件对应的Class类型的对象

三种方式调用Class类(反射源头)

  1. Object类的getClass()方法,判断两个对象是否是同一个字节码文件
//判断是否是同一个字节码对象
//Person p = new Person();
Class clazz = p.getClass();

面试题:请解释Object类中的所有方法以及每一个方法使用上的注意事项:

  • 对象克隆:public Object clone() throws CloneNotSupportdException;

    克隆对象所在的类一定要实现java.lang.Cloneable接口,而且子类只需要继续Object类的Clone()方法就可以成功实现克隆操作
  • 对象输出:public String toString()

    直接输出对象时会默认调用toString()方法
  • 对象比较:public boolean equals(Object obj)

    当保存Set集合时,会依靠hashCode()和equals()判断是否为重复对象
  • 取得对象的hash码:public int hashCode()

    可以理解为每一个类对象的唯一编码,比较时会先判断编码是否相同,而后再调用equals()比较内容;
  • 取得Class类对象:public Class<?> getClass();

    通过一个已经实例化好的对象进行对象的反射操作
  • 线程等待:public void wait() InterceptorException

    执行到此代码时线程要等待执行,一直到执行notify(),notifyAll()
  • 唤醒第一个等待线程:public void notify()
  • 唤醒全部等待线程:public void notifyAll();
  • 垃圾回收前释放:public void finalize() htrows Throwable;

    当使用gc回收无用垃圾空间时默认调用
  1. 静态属性Class,锁对象(Hiberate)
//当作静态方法的锁对象
//Person.class
Class clazz = Person.class
  1. Class类中静态方法forName(),读取配置文件
//读取配置文件
//Person.java
Class clazz = class.forName("类全限定名");

利用反射实例化对象

package cn.jishuz.demo;
class Student{
	public Student() {
		System.out.println("Student类的构造方法");
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "Student类的toString()方法";
	}
}
public class ReflectDemo {
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		Class<?> cls = Class.forName("cn.jishuz.demo.Student");
		// 相当于关键字new实例化对象,等价:Object obj = new Object();
		Object obj = cls.newInstance();
		System.out.println(obj);
	}
}

++必须要求类中存在无参构造方法,否则报错: java.lang.InstantiationException++

操作构造方法

可以解决上面实例化必须要无参构造的现象

在Class类里面定义了可以取得一个类之中构造方法的操作:

  • 取得类之中的全部构造(预先不知道构造的参数类型时可以先打印它的所有构造):public Constructor<?>[] getConstructors()
  • 取得类之中指定参数的构造:public Constructor getConstruct(Class<?>... parameterTypes)
package cn.jishuz.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

class Student{
	private String name;
	private Integer age;
	public Student(String name,Integer age) {
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "姓名:"+ this.name+",年龄:"+this.age;
	}
}
public class ReflectDemo {
	public static void main(String[] args) throws Exception {
		Class<?> cls = Class.forName("cn.jishuz.demo.Student");
		Constructor<?> cons = cls.getConstructor(String.class,Integer.class);
		// 相当于关键字new实例化对象,等价:Object obj = new Object();
//		Object obj = cls.newInstance();
		Object obj = cons.newInstance("TOM",20);
		System.out.println(obj);
	}
}

调用类中方法

++取得了类的实例化对象后就可以开始调用类中的方法。++

两种类型:

- 取得父类继承而来的方法:

1.取得全部方法:

public Method[] getMethods()
                    throws SecurityException

2.获取指定方法:

public Method getMethod(String name,Class<?>... parameterTypes)
                 throws NoSuchMethodException, SecurityException
- 取得本类定义的方法:

1.取得全部方法:

public Method[] getDeclaredMethods()
                            throws SecurityException

2.获取指定方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
                         throws NoSuchMethodException, SecurityException

范例:

package cn.jishuz.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

interface Message{
	public void get();
}

class Student implements Message{
	@Override
	public void get() {}
	public void fun(){}
	public void print(){}
}
public class ReflectDemo {
	public static void main(String[] args) throws Exception {
		Class<?> cls = Class.forName("cn.jishuz.demo.Student");
		Method met[] = cls.getMethods();
		for(int x= 0;x<met.length;x++){
			System.out.println(met[x].getName());
		}
	}
}
============运行结果=============
get
print
fun
wait
wait
wait
hashCode
getClass
equals
toString
notify
notifyAll

其它

取得方法修饰符:public int getModifiers();

  • 修饰符int转换为String:
    public static String toString(int mod);

取得方法的返回参数类型:public Class<?> getReturnType();

  • getSimpleName()得到简称

取得方法的参数:public Class<?>[] getParameterTypes();


取得所有抛出的异常:public Class<?>[] getExceptionTypes()


++反射调用类中的方法++:public Object invoke(Object obj,Object... args)

调用类中的属性(尽量不要去使用)

支持的方法有两类:

  1. 取得所有继承而来的属性:
  • 取得全部属性:public Field[] getFields()
  • 取得指定属性:public Field getField(String name)
  1. 取得本类定义的属性:
  • 取得全部属性:public Field[] getDeclaredFields()
  • 取得指定属性:public Field getDeclaredField(String name)
package cn.jishuz.demo;

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

interface Message{
	public static final String INFO = "hello world.";
}
class Person{
	private String name;
	private Integer age;
}
class Student extends Person implements Message{
	private String school;
	private Double price;
}
public class ReflectDemo {
	public static void main(String[] args) throws Exception {
		Class<?> cls = Class.forName("cn.jishuz.demo.Student");
		{//取得继承而来的全部属性
			Field fields[] = cls.getFields();
			for(int x= 0;x<fields.length;x++){
				System.out.println(fields[x]);
			}
			System.out.println("------------");
		}
		{//取得本类定义的全部属性
			Field fields[] = cls.getDeclaredFields();
			for(int x= 0;x<fields.length;x++){
				System.out.println(fields[x]);
			}
			System.out.println("------------");
		}
		{//取得父类属性
			Field fields[] = cls.getSuperclass().getDeclaredFields();
			for(int x=0;x<fields.length;x++){
				System.out.println(fields[x]);
			}
		}
	}
}
============运行结果=============
public static final java.lang.String cn.jishuz.demo.Message.INFO
------------
private java.lang.String cn.jishuz.demo.Student.school
private java.lang.Double cn.jishuz.demo.Student.price
------------
private java.lang.String cn.jishuz.demo.Person.name
private java.lang.Integer cn.jishuz.demo.Person.age

在Field类里面还定义有进行属性调用的方法:

  • 设置属性内容:public void set(Object obj,Object value)
  • 取得属性内容:public Object get(Object obj)

在Constrcutor、Method、Field三个类上有一个共同的父类AccessibleObject,在这个类里面定义了可以取消封装的方法:public void etAccessible(boolean flag);设置成true即可取消封装。

评论
发表评论