目的是在运行时可以加载到之前没有加载到jvm的。
正常使用类的步骤:
- 使用import导入类所在的包(java.lang.Class)
- 明确的使用类明程或者接口明程定义对象
- 通过关键字new进行类对象实例化(构造方法:java.lang reflect.Constructor)
- 产生对象可以使用“对象.属性”进行类中属性的调用(java.lang.reflect.Field)
- 通过“对象.方法()”调用类中方法(java.lang.reflect.Method)
附:反射的泛型几乎无用,使用的时候用“?”
附:如果想要使用Class类进行操作,那么就必须首先产生Class类的实例化对象
- Object类提供了一个返回Class类对象的方法:public Class<?> getClass()
- 利用类.class取得,日后见得最多的就是在Hibernate
- 利用Class类的static方法取得;public static Class<?> forName(String className) throws ClassNotFoundException
工厂设计模式最好利用反射机制解决耦合问题。
请解释Object类之中的所有方法以及每一个方法使用上的注意事项:
- 对象克隆:public Object clone() throws CloneNotSupportedException;
克隆对象所在的类一定要实现java.lang.Cloneable接口,而且子类只需要继续调用Object类的clone()方法就可以实现克隆操作。 - 对象输出 public String toString();
- 对象比较:public boolean equals(Object obj),当保存set集合时,会依靠hashCode()和equals()判断是否为重复对象
- 取得对象的hash码,public in hashCode();可以理解为每一个类对象的唯一编码,比较时会先判断编码是否相同,后比较内容
- 取得Class类对象,public Class<?> getClass();通过一个已经实例化好的对象进行对象的反射操作。
- 线程等待:public void wait() InterceptorException;执行到此代码时线程要等待执行,一直到执行notify()、notifyAll()。唤醒第一个等待线程public void notify(),唤醒全部等待线程public void notifyAll()。
Class<?> cls = Class.forName(".....Student");
//以下代码相当于用关键字new实例化对象,相当于Object obj = new Student();
Object obj = cls.newInstance();
上面的例子中可以看出,可以不通过new直接进行实例化操作。但是如果使用反射实例化类对象,必须要求类中存在有无参构造方法,只能够找到无参构造方法。此时需要取得类中的构造方法,传递所需要的参数后才可以执行。
取得类中的全部构造 public Constructor<?>[]
取得类中指定参数的构造 public Constructor
例子:取得String类的全部构造方法
Class<?> cls = Class.forName(“java.lang.String”);
Constructor<?> [] cons = cls.getConstructors(); 取得全部构造
即可输出。
如果想要进行指定构造方法的调用,就必须将关注点放在Constructor类型中。
看Constructor类。在此类中定义了一个实例化对象方法public T newInstance(Object… initargs) throws…
若是带参构造方法,则
Class<?> cls = Class.forName("…Student")
Constructor<?> cons = cls.getConstructor(String.class, Integer.class)
Object obj = cons.newInstance(“lisi”, 20);
和上面的无参构造进行比较
正式因为如果是通过构造方法实例化对象规格不统一。所以在进行简单Java操作时明确规定必须有无参构造方法。
调用类中的方法
类中的方法有两类,一个是从父类继承,一个是本类定义的。
- 取得父类继承而来的方法:
取得全部方法:
public Method[] getMethods() throws SecurityException
取得指定方法:
public Method getMethod(String name, Class<?>…parameterTypes) throws NoSuchMethodException, SecurityException;
- 取得本类定义的方法:
取得全部(公有?)方法:public Method[] getDeclaredMethods() throws SecurityException
取得指定方法:public Method getDeclaredMethod(String name, Class<?>… parameterTypes) throws NoSuchMethodException, SecurityException
Class<?> cls = Class.forName("....Student");
Method met[] = cls.getMethods();
现在的程序是直接调用了Method类中的toString()方法实现的输出,如果用户有需要也可以自己去整理方法的输出,可以使用到Method类的如下方法:
- 取得方法修饰符。 public int getModifiers();
该方法得到的是一串数字,因为在程序中找的不是public、static等关键字,而是关键字所代表的数字,如果要换成我们一眼能懂的信息,可以借助Modifier类完成,此类中可以直接利用方法取得将数字变为修饰符。
public static String toString(int mod)//
Modifier.toString(met[x].getModifiers)
取得方法的返回参数类型public Class<?> getReturnType();
met[x].getReturnType()//返回连带着包
met[x].getReturnType().getSimpleName()//返回的不带包名
取得方法的参数public Class<?> [] getParameterTypes();
Class<?> params[] = met[x].getParameterTypes();//获得的是全部参数
调用类中的属性(尽量不要使用)
关于类中的属性也可以直接利用反射进行操作,而支持的方法有两类:
取得所有继承而来的属性
- 取得全部属性
public Field[] getFields() throws SecurityException - 取得指定属性
public Field getField(String name) throws NoSuchMethodException, SecurityException
取得本类定义的属性
1.取得全部属性
public Field[] getDeclareFields() throws SecurityException
2.取得指定属性
public Field getDeclareField(String name) throws NoSuchMethodException, SecurityException
Class<?> cls = Class.forName(".....Student");
Field fields [] = cls.getFields();//继承而来的全部属性
= cls.getDeclareFields()//本类定义的属性
cls.getSuperclass().getDeclaredField;//取得父类属性
在Field类里面还定义有进行属性调用的方法
- 设置属性内容
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException - 取得属性内容
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException
在Constructor、Method、Field三个类上有一个共同的父类AccessibleObject,在这个类里面定义了可以取消封装的操作方法(如果不取消有异常)
Class<?> cls = Class.forName("....Student);
Object obj = cls.newInstance();
Field schoolField = cls.getDeclaredField("school");
schoolField.setAccessible(true)//取消封装
schoolField.set(obj,"大学");
web对反射的操作支持
在jsp中有一种技术——JavaBean,而且在jsp里面也配套有相应的操作方式。JavaBean核心在于简单Java类。
package vo;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Student implements Serializable{
private String name;
private Integer age;
private Double score;
}
此时有三种数据类型,并且要求完成setter和getter,在web项目中所建立的每一个*.java类最终会保存在WEB-INF/classes中,所以classes就是一个CLASSPATH。