java 反射机制

java 反射机制

Note:
1. 正常方式:引入需要的“包.类” —> 通过new实例化 —> 取得实例化对象
2. 反射方式:实例化对象 —> getClass()得到类 —> 得到完整的“包.类”名称

Class类的常用方法

序号方法描述
1Class forName(String className)传入完整的”包.类”名称得到这个类
2Constructor[] getConstructors()得到一个类的全部构造方法
3Fileds[] getDeclaredFields()得到本类单独定义的全部属性
4Filed[] getFileds()得到本类继承而来的全部属性
5Methods[] getMethods()所有的公有(public)方法,包括继承类的公有方法,也包括实现接口的方法
6Methods[] getDeclaredMethods()包括public,private,private,default的方法,包括实现接口的方法,不包括继承来的方法,
7Method getMethod(String name,Class… parameter)返回一个具体的Method对象
8Class[] getInterfaces()得到类的全部接口
9String getName()得到类的完整”包.类”名称
10Package getPackage()得到类的包
11Class getSuperClass()得到一个类的父类
12Object newInstance()得到类Class的实例化对象

(1)三种方法得到某个特定的类

1.使用Class.forName(String className)得到,也是推荐

Class<?> clazz1= Class.forName("org.apache.vlis.Agent");

2.使用某一个对象 X ,调用对象方法getClass()得到

Father father = new Father();
Class<?> clazz2 = father.getClass();

3.使用某一个类Class得到

Class<?> clazz3 = Father.class;

(2)通过在(1)得到了某个特定的类,接下来要实例化对象

1.通过使用newInstance()方法

Note:newInstance()方法,需要实例化的类必须有无参的构造函数

Class<?> clazz = Class.forName("org.apache.vlis.Father");
//类Father,必须有无参的构造函数
Father father = (Father) clazz.newInstance();

2.通过使用getConstructors()方法得到有参构造函数

Class<?> clazz = Class.forname("org.apache.vlis.Father");
Constructor<?> constructors[] = clazz.getConstructors();
Father father = (Father) constructors[index].newInstance("fatherName",47);

3.Constructor常用方法

序号方法描述
1int getModifiers()得到构造方法修饰符(public,private,protected)
2String getName()得到构造方法的名称
3Class getParameterTypes()得到参数的类型
4T newInstance(Object.. args)实例化,得到类的对象

(3)通过在(1)中得到了某个特定的类,然后得到具体的方法,在使用invoke(…)方法执行

  • Method 类中常用方法
序号方法描述
1int getModifiers()得到本方法修饰符(public,private,protected)
2String getName()得到方法的名称
3Class getParameterTypes()得到参数的类型
4Class getReturnType()得到方法的返回值
5Class getExceptionTypes()得到一个方法的全部抛出异常
6Object invoke(Object obj,Object… args)实例化,得到类的对象

基础Class

package vlis;
public class Thinking{
    private String name;
    public void setName(String Name){
        this.name = Name;
    }
    public String getName(){
        return this.name;
    }
    public Thinking(){
    }
    public void Print(){
        System.out.println("thinking_fioa")
    }
    public static void Println(String op,String name){
        System.out.println("thinking_fioa " +op+" "+name";
    }
}

1.反射调用多参的静态方法(public)

package vlis;
public class Client{
    public static void main(String [] args){
        try{
            Class<?> clazz = Class.forName("vlis.Thinking");
            Method print = clazz.getMethod("Print",new Class[]{String.class,String.class});
            print.invoke(null,new Object[] { " love "," fyj"});
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

2.反射调用非静态方法(public)

package vlis;
public class Client{
    public static void main(String [] args){
        try{
            Class<?> clazz = Class.forName("vlis.Thinking");
            Thinking thinking = (Thinking) clazz.newIntance();//Thinking类中一定要有无参构造函数
            Method print = clazz.getMethod("Print",new Class[]{String.class,String.class});
            print.invoke(thinking,new Object[] { " love "," fyj"});
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

3.反射调用非静态方法无参函数

package vlis;
public class Client{
    public static void main(String [] args){
        try{
            Class<?> clazz = Class.forName("vlis.Thinking");
            Thinking thinking = (Thinking) clazz.newIntance();//Thinking类中一定要有无参构造函数
            Method print = clazz.getMethod("Print");
            print.invoke(thinking);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

4.封装setXXX(…),getXXX(…),使反射得到的对象可以操作具体的属性

Note:如果类中有多个属性时,另写一个setter(…),getter(…)操作方法
- 基础类Father

package vlis;
public class Father {
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
    public void setAge(int Age){
        this.age = Age;
    }
    public int getAge(){
        return this.age;
    }
    public void Print(){
        System.out.println("thinking_fioa");
    }
    public Father(){
    }
}
  • Client类
package vlis;
public class Client{
    public static void main(String [] args){
        Class<?> clazz = null;
        try{
            clazz = Class.forName("vlis.Father");
        }catch(Exception e){
            e.printStackTrace();
        }
        Object obj = clazz.newInstance();
        setter(obj,"setName","thinking_fioa",String.class);
        System.out.println(" ---> " + getter(obj,"getName"));
        setter(obj,"setAge",5,int.class);
        System.out.println(" ---> "+ getter(obj,"getAge"));
    }
    //setter(...)方法中,需要加入一个参数:Class<?> type,否则,处理int,double,float,不行.
    public static void setter(Object obj,String methodName,Object value,Class<?> type){
        try{
            Method method= obj.getClass().getMethod(methodName,type);
            method.invoke(obj,value);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    public static Object getter(Object obj,String methodName){
        try{
            Method method = obj.getClass().getMethod(methodName);
            return method.invoke(obj)
        }catch(Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

(4)通过在(1)中得到了某个特定的类,然后得到具体的Field(Field就是值属性,区别出:Filed[] getFields(),Field[] getDeclaredFields())

  • Filed类常用的方法
序号方法描述
1Object get(Object obj)得到一个对象中属性的具体内容
2void set(Object obj,Object value)设置指定对象中属性的具体内容
3int getModifiers()得到属性的修饰符
4String getName()返回此属性的名称
5void setAccessible(boolean flag)设置一个属性是否可以被外部访问
6boolean isAccessible()判断属性是否可被外部访问
7static void setAccessible(AccessibleObject[] array,boolean flag)设置一组属性是否可被外部访问

1. 虽然在反射中可以使用类的getXXX(),setXXX(…),修改属性。但比较麻烦,也可能类并没有提供。可以采用直接操作Filed域,也更简单

//下面的代码中出现的类Father,是(3).4中所指的Father类
public class CLient{
    public static void main(String [] args){
        Class<?> clazz = null;
        try{
            clazz = Class.forName("vlis.Father");
        }catch(Exception e){
            e.printStackTrace();
        }
        Object obj = clazz.newInstance();
        Field nameField = clazz.getDeclaredField("name");
        //name是private,设置其可以访问
        nameField.setAccessible(true);
        nameField.set(obj,"thinking_fioa");
        System.out.println(nameField.get(obj));
    }
}

(5)通过反射来操作数组

  • Array(java.lang.reflect.Array)类常用的方法
序号方法描述
1Object get(Object array,int index)根据下标取得数组内容
2Object newInstance(Class componentType,int length)根据已有的数组类型开辟新的数组对象
3void set(Object array,int index,Object value)修改指定位置的内容

Note:特别提醒:对于一个数组来说,想要得到Class<?> type需要使用array.getClass().getComponentType();

public class Client {
    public static void main(String args[]) throws Exception{
        int temp[] = {1,2,3};
        Class<?> clazz = temp.getClass().getComponentType();
        System.out.println("thinking_fioa ---> " + clazz.getName());
        Array.set(temp, 2, 4);
        System.out.println("thinking_fioa --->" + Array.get(temp, 2));
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值