栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射学习笔记

1、访问字段

对任意的一个Object实例,获取了它的Class,就可以获取一切信息,通过反射读写字段会破坏对象的封装性。
Java提供了一下方法来通过Class实例获取字段信息:

  • Field getField(name): 根据字段名获取某个public的field(包括父类)
  • Field getDeclaredField(name): 根据字段名获取当前类的某个field(不包括父类)
  • Field[] getFields(): 获取所有public的field(包括父类)
  • Field[] getDeclaredFields(): 获取当前类的所有字段(不包括父类)
public class FieldTest {
    
    public static void main(String[] args) throws NoSuchFieldException {
        Class clazz = Student.class;
        System.out.println(clazz.getField("age"));
        System.out.println(clazz.getField("name"));
        System.out.println(clazz.getDeclaredField("address"));
    }

    class Student extends Person{
        public int age;
        private String address;
    }

    class Person{
        public String name;
    }
}

运行结果:
public int Reflect.FieldTest$Student.age
public java.lang.String Reflect.FieldTest$Person.name
private java.lang.String Reflect.FieldTest$Student.address

获取到一个Field对象,可以通过Field对象获取到该对象的名称、类型、修饰符、值等信息。

  • getName(): 返回字段名称
  • getType(): 返回字段类型,是一个Class实例
  • getModifiers(): 返回字段的修饰符,是一个int,不同bit表示不同含义
 		Field s = String.class.getDeclaredField("value");
        int j = s.getModifiers();
        System.out.println(s.getName());
        System.out.println(s.getType());
        System.out.println(Modifier.isPublic(j));
        System.out.println(Modifier.isAbstract(j));
        System.out.println(Modifier.isPrivate(j));
        System.out.println(Modifier.isStatic(j));

执行结果:
value
class [C
false
false
true
false

使用get(Object)方法获取Field的值

 	Object person = new Person("Mark");
    Class claz = person.getClass();
    Field fie = claz.getDeclaredField("name");
    fie.setAccessible(true);//无论是public或者private,一律允许访问
    Object value = fie.get(person);
    System.out.println(value);
	static class Person{
        public String name;

        public Person(String name){
            this.name = name;
        }
    }
执行结果:
Mark

使用Field.set(Object,Object)实现设置字段值,第一个参数是指定的实例,第二个参数是待修改的值。

 Person person = new Person("Mark");
 System.out.println(person.getName());
 Class claz = person.getClass();
 Field fie = claz.getDeclaredField("name");
 fie.setAccessible(true);//无论是public或者private,一律允许访问
 //设置字段值
 fie.set(person, "John");
 System.out.println(person.getName());
 
 运行结果:
 Mark
 John
2、 调用方法

通过Class实例可以获取所有Method的信息,Java提供了一下几个方法来获取Method。

  • Method getMothod(name, Class…): 获取某个public的Method(包括父类)
  • Method getDeclaredMethod(name, Class…): 获取当前类的某个Method(不包括父类)
  • Method[] getMethods(): 获取所有public的Method(包括父类)
  • Method[] getDeclareMethods(): 获取当前类的所有Method(不包括父类)
//反射获取方法
public class MethodTest {

    public static void main(String[] args) throws NoSuchMethodException {
        Class clazz = Student.class;
        //有参public方法
        System.out.println(clazz.getMethod("getScore", String.class));
        //有参private方法
        System.out.println(clazz.getDeclaredMethod("getPhone", int.class));
        //无参public父类方法
        System.out.println(clazz.getMethod("getName"));
    }

    class Student extends Person{
        public int getScore(String score){
            return 100;
        }

        private int getPhone(int phone){
            return 12345;
        }
    }

    class Person{
        public String getName(){
            return "Mark";
        }
    }
}

执行结果:
public int Reflect.MethodTest$Student.getScore(java.lang.String)
private int Reflect.MethodTest$Student.getPhone(int)
public java.lang.String Reflect.MethodTest$Person.getName()

获取到Method对象,就可以获取该方法的所有信息,java提供了以下方法对方法进行操作:

  • getName(): 返回方法名称
  • getReturnType(): 返回方法返回值类型,是一个Class实例
  • getParameterTypes(): 返回方法的参数类型,是一个Class数据
  • getModifiers():返回方法的修饰符,是一个int类型,不同数字代表不同含义
//获取方法的详细信息
Method method = clazz.getMethod("getScore", String.class);
System.out.println(method.getName());//方法名
System.out.println(method.getReturnType());//返回类型
System.out.println(method.getParameterTypes());//方法参数类型
System.out.println(method.getModifiers());//方法的修饰符
        
执行结果:
getScore
int
[Ljava.lang.Class;@6ff3c5b5
1
2.1 调用方法

获取到一个Method方法时,不仅可以获取该方法对象的所有信息,还可以对方法进行操作。调用方法。
利用反射调用String的length()方法,使用Method的invoke方法就相当于调用该方法,invoke的第一个参数是对象实例,后面的可变参数与方法参数一致。

 String str = "Hello World";
 Method m1 = String.class.getMethod("length");
 int length = (int) m1.invoke(str);
 System.out.println(length);

调用非public方法,使用Method.setAccessible(true)方法

//调用private方法
User user = new User();
Method m2  = user.getClass().getDeclaredMethod("setName", String.class);
m2.setAccessible(true);
String band = (String) m2.invoke(user,"Oasis");
System.out.println(band);

static class User{
        String name;
        private String setName(String name){
            return name;
        }
    }

执行结果:
Oasis

处理多态:子类覆写了父类的方法,从父类获取到的方法,作用于子类时,调用的是子类的方法。
结论:使用反射调用方法时,仍然遵守多态规则。

//处理多态
Method m3 = Animals.class.getMethod("run");
m3.invoke(new Cat());
class Animals{
    public void run(){
         System.out.println("Animals:I can run");
    }
}

class Cat extends Animals{
     public void run(){
         System.out.println("Cat:I can run");
     }
}

执行结果:
Cat:I can run
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/945219.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号