反射
反射:指的是对象的反向处理,根据对象倒推类的组成
正向处理:根据类产生对象:Person per = new Person(); 先有类再有对象
反射核心类:Class类(专门描述其他类的组成)
Object类中取得对象的class对象:public final native Calss<> getClass();
Class类描述接口与类的组成,Class对象有JVM在第一次加载类时产生,并且全局唯一。
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,AnnotatedElement
构造方法:private Class(ClassLoader loader){ //构造私有,并没有提供取得Class类的方法
classLoader = loader;
}
取得任意类Class对象方法:类的反射对象有且只有一个
1、调用对象.getClass()取得Class对象 Object提供的方法,所以任意类都有这个方法
2、类名称.calss取得Class对象
3、Class.forName(类全名称)取得Class对象
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Date date = new Date();
System.out.println(date);
//1、取得Class对象的方法:调用对象.getClass()取得Class对象
System.out.println(date.getClass()+" "+date.getClass().hashCode());
//2、取得Class对象的方法:类名称.calss取得Class对象
System.out.println(Date.class+" "+Date.class.hashCode());
//3、取得Class对象的方法:Class.forName(类全名称)取得Class对象
System.out.println(Class.forName("java.util.Date")+" "+Class.forName("java.util.Date").hashCode());
System.out.println(int.class);
System.out.println(Integer.class);
}
}
结果:
Wed Jul 31 08:00:44 CST 2019
class java.util.Date 1836019240
class java.util.Date 1836019240
class java.util.Date 1836019240
int
class java.lang.Integer
通过反射实例化类对象: newInstance() :public T newInstance() throws InstantiationException,IllegalAccessException
Class<Date> dateClass = Date.class;
Date date = dateClass.newInstance();
System.out.println(date);
通过反射可以动态破坏封装:可以为所欲为
反射的工厂模式:增加新的子类,不用改代码,(简单工厂)
public class FactoryAndReflect {
public static void main(String[] args) {
Factory.getInstance("reflect.WaterMelon").eat();
}
}
class Factory{
public static IFruit getInstance(String fruitName) {
IFruit fruit = null;
Class<?> cla = null;
try {
cla = Class.forName(fruitName);
try {
fruit = (IFruit) cla.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return fruit;
}
}
interface IFruit{
void eat();
}
class Apple implements IFruit {
@Override
public void eat() {
System.out.println("eat an apple");
}
}
class Orange implements IFruit {
@Override
public void eat() {
System.out.println("eat an Orange");
}
}
class WaterMelon implements IFruit {
@Override
public void eat() {
System.out.println("eat a WaterMelon");
}
}
反射与类操作
1、取得父类&父接口信息
1.1、取得包信息—Package(描述包信息的类):
public Package getPacket(); Class类提供
public class Package implements java.lang.reflect.AnnotatedElement
1.2、构造方法:
public Constructor<T> getConstructor(Class<?>...parameterTypes) throws NoSuchMethodException,SecurityException
1.3、普通方法(取得类中普通方法的类):
public Method getMethod(Stringname,Class<?>...parameterTypes) throws NoSuchMethodException,SecurityException
1.4、属性:
public Field getField(Stringname) throws NoSuchFieldException,SecurityException
1.5、取得父类的Class对象:getSuperClass():Class<? Super T> ?:任意类型,但必须是T的父类
1.6、取得实现的父接口Class对象:getInterfaces():Calss<?>[]
2、反射与构造方法—Constructor(描述类构造方法信息):只能拿到本类的构造方法,并不能拿到父类的(与继承无关)
2.1、取得本类中指定参数类型的构造方法
public Constructor<T> getConstructor(Class<?>...parameterTypes)//只能取得权限为Public的构造方法
public Constructor<T> getDeclaredConstructor(Class<?>...parameterTypes)//取得所有权限为的构造方法
2.2、取得本类中所有构造方法
public Constructor<?>[] getConstructors() throws SecurityException//取得类中所有权限为Public的构造方法
public Constructor<?>[] getDeclaredConstructors() throws SecurityException//取得类中所有权限的构造方法
public classText{
publicstaticvoidmain(String[]args){
Class<Person>personClass=Person.class;
{
Constructor<?>[]constructors=personClass.getConstructors();
for(Constructorconstructor:constructors){
System.out.println(constructor);
}
}
System.out.println("--------------------------------------------");
{
Constructor<?>[]constructors=personClass.getDeclaredConstructors();
for(Constructorconstructor:constructors){
System.out.println(constructor);
}
}
System.out.println("--------------------------------------------");
}
}
classPerson{
privateStringname;
privateintage;
privatePerson(){
}
Person(intage){
}
protectedPerson(Stringname){
this.name=name;
}
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
}
结果:
public reflect.Person(java.lang.String,int)
--------------------------------------------
public reflect.Person(java.lang.String,int)
protected reflect.Person(java.lang.String)
reflect.Person(int)
private reflect.Person()
--------------------------------------------
Class类的newInstance()实际上是调用类的无参构造,如果类中没有无参构造或者权限不是public(权限不够,不同包下,且没有继承关系),此方法无法使用。
关注Constructor类的如下方法:public T newIstance(Object…initargs)
若类中没有无参构造,则只能调用Contructor类提供的newInstance方法使用有参构造来实例化对象
Class<Person> personClass=Person.class;
//personClass.newInstance();//实际上是调用类的无参构造,private不可用
//取得有参构造
Constructor constructor=personClass.getConstructor(String.class,int.class);
//实例化对象,相当于调用Person("jah",90)
Person person=(Person)constructor.newInstance("zhaofan",20);
System.out.println(person);
3、普通方法:不能取得构造方法
3.1、取得类中指定名称与参数的普通方法):
public Method getMethod(Stringname,Class<?>...parameterTypes) throws NoSuchMethodException,SecurityException
public Method getDeclaredMethod(Stringname,Class<?>...parameterTypes throws NoSuchMethodException,SecurityException
3.2、取得类中的所有的普通方法
取得本类以及父类中所有权限为public的普通方法(包括静态方法)
public Method[] getMethods() throws SecurityException
取得本类中所有方法(包括private方法,不能取得父类的方法):
public Method[] getDeclaredMethods() throws SecurityException
3.3、Method类中提供的调用普通方法
public Object invoke(Object obj,Object...args) throws IllegalAccessException,IllegalArgumentException //反射调用普通方法 obj是类的实例化对象
args:普通方法参数
//1.取得person类class对象
Class<Person>personClass=Person.class;
//2.取得方法
String setNameMothod="set"+initCap(args[0]); //initCap自定义的将首字母变大写
String getNameMothod="get"+initCap(args[0]);
Method setName=personClass.getMethod(setNameMothod,String.class);
Method getName=personClass.getDeclaredMethod(getNameMothod);
//3.取得实例化对象
Person person=personClass.newInstance();
//4.使用方法
setName.invoke(person,"zhaofan");
System.out.println(getName.invoke(person));
4、反射与普通属性
4.1、取得类中指定名称属性
public Field getField(String name) throws NoSuchFieldException,SecurityException
public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException
4.2、取得类中所有属性——同Method
public Field[] getFields() throws SecurityException 本类和父类中的public属性
public Field[] getDeclaredFields() throws SecurityException 本类中所有属性
4.3、Field类提供的设置与取得值方法
设置属性值: obj:类的实例化对象 value:要设置的值
public void set(Object obj,Object value) throws IllegalArgumentException,IllegalAccessException
取得属性值: obj:类的实例化对象
public Object get(Object obj) throws IllegalArgumentException,IllegalAccessException
取得属性类型
public Class<?> getType()
5、动态破环封装(反射特性)
Constructor、Method、Filed类都继承AccessibleObject类,此类中有一个破坏封装的方法
public class AccessibleObject implements AnnotatedElement
public void setAccessible(boolean flag) throws SecurityException //为true时破坏封装
时限为:在一次JVM进程中,且只能通过反射调用
public static void main(String[]args) throwsIllegalAccessException,InstantiationException,NoSuchFieldException{
Class<Person>personClass=Person.class;
Personperson=null;
person=personClass.newInstance();
Field[]fields=personClass.getFields();
Fieldfield=personClass.getDeclaredField("age");
//动态破坏封装
field.setAccessible(true);
field.set(person,25); set只能通过
System.out.println(field.get(person));
System.out.println(field.getType());
}