反射和枚举

目录

反射

class类

 Field类

Method类

 Constructor 类

泛型类实现

总结

枚举类

枚举类创建

 Enum类的部分方法

枚举与反射


反射

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

class类

java程序经过了运行和编译两个过程。程序编译之后生成class文件(class文件是二进制文件),class文件经过JVM的类加载器加载进入内存,JVM的解析器对内存的class文件进行解析,产生机器可以识别的机器语言。

类加载器加载的过程中,会创建Class类的实例java.lang.Class,通过这个对象,可以访问到类的任何属性,而反射就可以做到这一点。

如何获得Class对象

class Person {
    private String name;
    public int age;

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("这是有两个参数的私有的构造方法  " + name + age);
    }
    public Person(String name) {
        this.name = name;
        System.out.println("这是有一个参数的公开的构造方法" + name + age);
    }

    public Person() {
        System.out.println("这是没有参数的公开的构造方法");
    }

    private void print(String name, int age) {
        System.out.println("这是有两个参数的私有的普通方法" + name + age);
    }

    public void print() {
        System.out.println("这是没有参数的公开的普通方法");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  1. 通过Class类的forName方法获得
  public static void main(String[] args) throws ClassNotFoundException {
        Class c=Class.forName("反射.Person");
        System.out.println(c);
    }

2、通过类名.class来获得

 public static void main(String[] args) {
        Class<?> c=Person.class;
    }

3、通过类的实例化对象的getClass()方法来获得

 public static void main(String[] args) {
        Person person=new Person();
        Class c=person.getClass();
        System.out.println(c);
    }

 借助Class的newInstance方法可以创建Class类对象所指代的类(Person)的实例化对象

  public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //得到Class类的实例化对象,指向了Person这个对象
        Class<?> c=Class.forName("反射.Person");
        //构建Person类的实例化对象
      Person person=  (Person) c.newInstance();
      //就可以调用Person类的属性了
     person.print();
     //私有的方法不可以直接访问,如果想要调用私有的属性,需要借助Field类,Method类,Construction类的实例化对象来实现
     person.print("张三",10);
    }

 class类的某一些方法来实例化Field类,Method类,Construction类的实例化对象

 Field类

表示类的成员变量/类的属性

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        //得到Class类的实例化对象
       Class c= Class.forName("反射.Person");
       //创建Filed类,这个Field类的实例化对象指向了name这个变量
      Field field= c.getDeclaredField("name");
      //创建Person类
      Person person=(Person)  c.newInstance();
      //借助set方法更改person对象的属性(field对象指代的属性)
      field.set(person,"zhangsan");
      //  field.set(person,10);   //一定是field对象指代的属性
      //借助get方法得到person对象的属性(field对象指代的属性)
       String name=(String) field.get(person);
        System.out.println(name);
        System.out.println(person);
    }

如果直接访问私有属性,会报错

 需要调用field.setAccessible(true);来设置访问权限,让私有属性可以被访问

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class c = Class.forName("反射.Person");
        //指定访问了私有属性
        Field field = c.getDeclaredField("age");
        field.setAccessible(true);
        Person person = new Person();
        field.set(person, 10);
        int age =(int) field.get(person);
        System.out.println(age);
        System.out.println(person);
    }

Method类

代表类的方法

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class c = Class.forName("反射.Person");
        //指定访问了print方法,这个print的方法没有参数
        Method method = c.getDeclaredMethod("print");
        Person person = new Person();
        //传入参数,调用指定的print方法
        method.invoke(person);

        //调用私有方法
        Class c1 = Class.forName("反射.Person");
        //指定访问了print方法,这个print的方法参数是String和int
        Method method1 = c1.getDeclaredMethod("print",String.class,int.class);
        method1.setAccessible(true);
        Person person1 = new Person();
        //传入参数,调用指定的print方法
        method1.invoke(person1,"zhangsan",5);

    }

 Constructor 类

访问类的构造方法

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class c = Class.forName("反射.Person");
        //获取构造方法,构造方法的参数是String
        Constructor constructor=c.getDeclaredConstructor(String.class);
      //通过构造方法创建Person类的实例
       Person person=(Person) constructor.newInstance("zhangsan");
        System.out.println(person);

        Class c1 = Class.forName("反射.Person");
        //获取构造方法,构造方法的参数是String,int
        Constructor constructor1=c1.getDeclaredConstructor(String.class,int.class);
        constructor1.setAccessible(true);
        //通过构造方法创建Person类的实例
        Person person1=(Person) constructor1.newInstance("zhangsan",9);
        System.out.println(person1);
    }

泛型类实现

class Student<K> {
 //  K[]arr=(K[])new Object[10];//创建泛型数组;这个方式不会报错,但是实际上也不正确
    
    K[]table;
  public Student(Class<?> c,int sz){
   table=(K[])Array.newInstance(c,10);
  }
  public void add(K value) {
        table[0] = value;
    }
    public Object get() {
        return table[0];
    }
}
public class Text {
    public static void main(String[] args) throws ClassNotFoundException {
        Student<Integer> student = new Student<>(Integer.class,10);
        student.add(10);
      Object a=  student.get();
        System.out.println(a);
    }

总结

反射可以获得类的任何成员,哪怕是私有的也可以访问,经常用于框架构建

枚举类

枚举类创建

public enum Text {
    RED,BLACK,GREEN;

    public static void main(String[] args) {
        switch (BLACK) {
            case RED:
                System.out.println("Red");
                break;
            case BLACK:
                System.out.println("BLACK");
                break;
            case GREEN:
                System.out.println("GREEN");
                break;
        }
    }
}

enum表示创建枚举类,Text是这个枚举类的名称

public enum Text {
    RED,BLACK,GREEN;
}

Java 中的每一个枚举都继承自 java.lang.Enum 类。当定义一个枚举类型时,每一个枚举类型成员都可以看作是 Enum 类的实例。这些枚举成员默认都被 final、public, static 修饰,当使用枚举类型成员时,直接使用枚举名称调用成员即可。

 每创建一个类都要调用提供的构造方法,构造方法中传入的name是枚举常量的名称,传入的ordinal表示枚举的序号


public enum Text {

RED,BLACK,GREEN;

}

 以上等价于

new Enum<Text>(RED,0)

new Enum<Text>(BLACK,1)

new Enum<Text>(GREEN,2)

 Enum类的部分方法

 1、values方法

    public static void main(String[] args) {
        //类名.values()调用枚举类的values方法,返回枚举成员构成的数组
        //每一个枚举成员都是一个枚举对象,可以使用类名(枚举名称)直接调用
        Text[] text = Text.values();
        for (Text o:
          text   ) {
            System.out.println(o);
        }
    }

2、compareTo方法

  public static void main(String[] args) {
        System.out.println(Text.RED.compareTo(Text.GREEN));
    }

3、valueof方法

  public static void main(String[] args) {
        Text text=Text.valueOf("RED");
        System.out.println(text);
    }

4、ordinal()

 public static void main(String[] args) {
        Text text=Text.valueOf("BLACK");
        System.out.println(text);
        System.out.println(text.ordinal());
    }

但是打开Enum类的所有方法,发现并不存在values方法

 那么他是怎么来的呢?

新创建一个类

public enum TextEnum {
    RED,Green;
}

 values方法由编译器自动添加

枚举与反射

 不能创建反射类型的实例

 所以枚举类型是非常安全的,连反射都不能创建枚举类型

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值