Java——反射

反射

反射:指的是对象的反向处理,根据对象倒推类的组成

正向处理:根据类产生对象: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.取得personclass对象

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());

}

类加载器ClassLoader:https://blog.csdn.net/Sophiahaha/article/details/98182602

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值