35/365 java 反射 Reflection Class类

1.动态语言 静态语言

动态语言:

  • 运行时可以改变自身结构的语言
  • eg: JavaScript, C#, PHP, Python

静态语言:

  • 运行时结构不可变的语言
  • eg: Java, C, C++

Java 不是动态语言,但通过反射机制获得了类似动态语言的特性,具有了一定的动态性,使得代码更加灵活。

2. Reflection 反射

反射机制使得程序可以在运行期间使用反射机制的API类获取任何类的内部信息,并直接操作类所有的属性和方法(包括private修饰的属性和方法)。

类加载结束后,在堆内存的方法区中产生了一个Class类型的对象,这个对象包含了类的所有信息。我们可以通过这个对象来了解类,所以称为反射。(与通过类来创建对象的过程相反)

一个类只有一个Class类型的对象。

 代码示例:

package AnnotationTest;

public class A3 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取类的Class对象
        Class<?> c1 = Class.forName("AnnotationTest.A31");
        System.out.println(c1.toString());
        System.out.println(c1.getName());
        System.out.println(c1.hashCode());

        Class<?> c2 = Class.forName("AnnotationTest.A31");
        Class<?> c3 = Class.forName("AnnotationTest.A31");
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        //hashcode相同说明是同一个对象,说明一个类只有一个Class类型的对象
    }
}

//用一个实体类作示例,来取得它的Class类型的对象
class A31{
    int di;
    int num;
    String name;
    boolean falg;

    A31(){

    }

    public A31(int di, int num, String name, boolean falg) {
        this.di = di;
        this.num = num;
        this.name = name;
        this.falg = falg;
    }


    public int getDi() {
        return di;
    }

    public void setDi(int di) {
        this.di = di;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isFalg() {
        return falg;
    }

    public void setFalg(boolean falg) {
        this.falg = falg;
    }

    @Override
    public String toString() {
        return "A31{" +
                "di=" + di +
                ", num=" + num +
                ", name='" + name + '\'' +
                ", falg=" + falg +
                '}';
    }
}

3.Class类

特征:

 方法:

4.获取Class类型的对象的五种方法

方法一:通过包名+类名获取Class对象,会抛出ClassNotFoundException异常。
 Class<?> c1 = Class.forName("AnnotationTest.A31");
 System.out.println(c1.hashCode());
方法二:通过类的对象获取Class对象
 A31 a = new A31();
 Class c2 = a.getClass();
 System.out.println(c2.hashCode());
 方法三:通过类的class属性获取Class对象。该方法最安全,性能最高。
 Class<A31> c3 = A31.class;
 System.out.println(c3.hashCode());
 方法四:通过子类的Class对象获取父类的Class对象
Class c4 = c2.getSuperclass();
System.out.println(c4 + " " + c4.hashCode());
方法五:通过基本内置类型的包装类型的type属性获取Class对象
 Class<Integer> c5 = Integer.TYPE;
 System.out.println(c5 + " " + c5.hashCode());

完整代码示例:

package AnnotationTest;

public class A3 {
    public static void main(String[] args) throws ClassNotFoundException {
       //方法一:通过包名+类名获取Class对象
        Class<?> c1 = Class.forName("AnnotationTest.A31");
        System.out.println(c1.hashCode());

        //方法二:通过类的对象获取Class对象
        A31 a = new A31();
        Class c2 = a.getClass();
        System.out.println(c2.hashCode());

        //方法三:通过类的class属性获取Class对象
        Class<A31> c3 = A31.class;
        System.out.println(c3.hashCode());

        //方法四:通过子类的Class对象获取父类的Class对象
        Class c4 = c2.getSuperclass();
        System.out.println(c4 + " " + c4.hashCode());

        //方法五:通过基本内置类型的包装类型的type属性获取Class对象
        Class<Integer> c5 = Integer.TYPE;
        System.out.println(c5 + " " + c5.hashCode());

    }
}


class A31 extends Object{
    int di;
    int num;
    String name;
    boolean falg;

    A31(){

    }

    public A31(int di, int num, String name, boolean falg) {
        this.di = di;
        this.num = num;
        this.name = name;
        this.falg = falg;
    }


    public int getDi() {
        return di;
    }

    public void setDi(int di) {
        this.di = di;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isFalg() {
        return falg;
    }

    public void setFalg(boolean falg) {
        this.falg = falg;
    }

    @Override
    public String toString() {
        return "A31{" +
                "di=" + di +
                ", num=" + num +
                ", name='" + name + '\'' +
                ", falg=" + falg +
                '}';
    }
}

5.哪些类型可以有Class类型的对象?

  • class: 外部类,静态内部类,成员内部类,局部内部类,匿名内部类
  • interface
  • anntation
  • 数组: 只要数组类型和维度相同,数组就会拥有同一个Class类的对象
  • enum
  • 基本数据类型的包装类
  • void

示例代码:

package AnnotationTest;

import java.lang.annotation.ElementType;

public class A4 {
    public static void main(String[] args) {
        Class c1 = Object.class;
        Class c2 = Runnable.class;
        Class c3 = Override.class;
        Class c4 = Integer.class;
        Class c5 = int[].class;
        Class c6 = int[][].class;
        Class c7 = ElementType.class;
        Class c8 = void.class;
        Class c9 = Class.class;

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);



        int[] a = new int[10];
        int[] b = new int[99];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值