java基础知识(十一)java反射机制(上)

java.lang.Class类详解

java Class类详解

一、class类

  Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时系统(JVM)对所有对象进行运行时类型标识,即Class对象,JVM可以通过该对象操作相应的类(如选准正确的方法执行)。

  Class类用于封装被装入JVM中类(类或接口)的信息(类名、类型属于class、interface、enum还是annotation),是java反射机制的基础,通过Class类我们可以获得关于一个类的相关信息。

  在程序运行时,如果需要生成某个对象,这时JVM首先检测这个类的Class对象是否已经加载(关于类 的加载会咋后面讲到),如果没有,JVM就会根据文件名查找.class文件将其载入,用于创建所需要的实例。JVM为每个类管理一个独一无二的Class对象(前提使用了同一个类加载器)。

  基本数据类型(boolean、byte、char、short、int、long、float 和 double)和关键字void也对应一个Class对象。另外,每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。

  Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。

1、获取某个类对应的Class对象的三种方法

  要想对JVM中Class对象封装的类信息进行访问,首先的获取对应类的Class对象,我们可以通过以下三种方式实现:

  a、通过Object的getClass()方法获取(所有的java对象都具备这个方法)

  b、使用.class的方式(使用类名加“.class”的方式即会返回与该类对应的Class对象,不需要创建该类的对象)

  c、使用Class.forName()方法,该方法据类名(字符串,包括类所在的包,如com.baidu.User)获取与该类关联的Class对象。

  下面是一段代码示例:

public class ObtainClass {

    public static void main(String[] args) {
        try {
            String str1 = "abc";
            System.out.println("通过Object的getClass()方法获取 : " + str1.getClass());
            System.out.println("使用.class的方式获取 : " + String.class);
            System.out.println("使用Class.forName()方法获取 : " + Class.forName("java.lang.String"));
            System.out.println(str1.getClass() == String.class);
            System.out.println(str1.getClass() == Class.forName("java.lang.String"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}

  由上面代码可以看出,每个类都对应唯一的Class对象。

2、Class类的常用方法

public class ClassTest {
    public static void main(String[] args) {
        try {
            System.out.println("返回与带有给定字符串名的类或接口相关联的 Class 对象 : " + Class.forName("com.classTest.classload.CTest"));
            System.out.println("以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称 : " + Class.forName("com.classTest.classload.CTest").getName());
            System.out.println("获取此类的包 : " + Class.forName("com.classTest.classload.CTest").getPackage());
            System.out.println("使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class 对象 : " + Class.forName("com.classTest.classload.CTest", true, ClassLoader.getSystemClassLoader()));
            System.out.println("返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class : " + Class.forName("com.classTest.classload.CTest").getSuperclass());
            System.out.println("返回源代码中给出的底层类的简称 : " + Class.forName("com.classTest.classload.CTest").getSimpleName());
            System.out.println("获取此类的标记 : " + Class.forName("com.classTest.classload.CTest").getSigners());

            CTest ct = new CTest();
            System.out.println("如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null : " + ct.annotationType());
            System.out.println("返回 Java Language Specification 中所定义的底层类的规范化名称 : " + Class.forName("com.classTest.classload.CTest").getCanonicalName());
            System.out.println("返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口 : " + Class.forName("com.classTest.classload.CTest").getClasses());
            System.out.println("返回该类的类加载器 : " + Class.forName("com.classTest.classload.CTest").getClassLoader());
            System.out.println("返回表示数组组件类型的 Class : " + Class.forName("com.classTest.classload.CTest").getComponentType());

            System.out.println("返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 : " + Class.forName("com.classTest.classload.CTest"));
            System.out.println("返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法 : " + Class.forName("com.classTest.classload.CTest").getConstructors().length);

            System.out.println("返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 : " + Class.forName("com.classTest.classload.CTest").getDeclaredField("age").getName());
            System.out.println("返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段 : " + Class.forName("com.classTest.classload.CTest").getDeclaredFields().length);
            System.out.println("返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 : " + Class.forName("com.classTest.classload.CTest").getField("str"));
            System.out.println("返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段 : " + Class.forName("com.classTest.classload.CTest").getFields().length);

            System.out.println("返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法 : " + Class.forName("com.classTest.classload.CTest").getDeclaredMethod("annotationType").getName());
            System.out.println("返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法 : " + Class.forName("com.classTest.classload.CTest").getDeclaredMethods().length);
            System.out.println("如果此 Class 对象表示某一方法中的一个本地或匿名类,则返回 Method 对象,它表示底层类的立即封闭方法 : " + Class.forName("com.classTest.classload.CTest").getEnclosingMethod());
            System.out.println("返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 : " + Class.forName("com.classTest.classload.CTest").getMethod("annotationType"));
            System.out.println("返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法 : " + Class.forName("com.classTest.classload.CTest").getMethods().length);

            System.out.println("返回此类或接口以整数编码的 Java 语言修饰符 : " + Class.forName("com.classTest.classload.CTest").getModifiers());

            System.out.println("如果此 Class 对象表示一个注释类型则返回 true : " + Class.forName("com.classTest.classload.ETest").isAnnotation());
            System.out.println("当且仅当底层类是匿名类时返回 true : " + Class.forName("com.classTest.classload.ETest").isAnonymousClass());
            System.out.println("判定此 Class 对象是否表示一个数组类 : " + Class.forName("com.classTest.classload.ETest").isArray());
            System.out.println("判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口 : " + Class.forName("com.classTest.classload.ETest").isAssignableFrom(Class.forName("com.classTest.classload.ETest")));
            System.out.println("当且仅当该类声明为源代码中的枚举时返回 true : " + Class.forName("com.classTest.classload.ETest").isEnum());
            System.out.println("判定指定的 Object 是否与此 Class 所表示的对象赋值兼容 : " + Class.forName("com.classTest.classload.CTest").isInstance(Class.forName("com.classTest.classload.CTest").newInstance()));
            System.out.println("判定指定的 Class 对象是否表示一个接口类型 : " + Class.forName("com.classTest.classload.CTest").isInterface());
            System.out.println("当且仅当底层类是本地类时返回 true : " + Class.forName("com.classTest.classload.CTest").isLocalClass());
            System.out.println("当且仅当底层类是成员类时返回 true : " + Class.forName("com.classTest.classload.CTest").isMemberClass());
            System.out.println("判定指定的 Class 对象是否表示一个基本类型 : " + Class.forName("com.classTest.classload.CTest").isPrimitive());
            System.out.println("如果此类是复合类,则返回 true,否则 false : " + Class.forName("com.classTest.classload.CTest").isSynthetic());
            System.out.println("创建此 Class 对象所表示的类的一个新实例 : " + Class.forName("com.classTest.classload.CTest").newInstance().toString());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

class CTest implements Annotation{
    private int age;
    private String name;
    public String str;

    public Class<? extends Annotation> annotationType() {
        return CTest.class;
    }

    @Override
    public String toString() {
        return "CTest{" +
                "age=" + age +
                ", name=‘" + name + ‘\‘‘ +
                ", str=‘" + str + ‘\‘‘ +
                ‘}‘;
    }
}

enum ETest{
    CN,
    EN
}

二、Method类

  Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

public class MethodTest {

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("com.classTest.classload.MT");
        Method[] m = clazz.getMethods();
        for (Method mh : m) {
            System.out.print(mh.getName() + " | " + mh.getDefaultValue() + " | " + mh.getReturnType());
            Class[] c = mh.getParameterTypes();
            System.out.print(" | len = " + c.length + " | ");
            for (Class tv : c) {
                System.out.print("  " + tv.getName());
            }
            System.out.println();
        }

        Method method = clazz.getMethod("mt", String.class);
        method.invoke(clazz.newInstance(), "test method");// 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法
    }

}

class MT {
    public String mt(String str) {
        System.out.println(str);
        return str;
    }
}

三、Field类

  Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

public class FieldTest {

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName("com.classTest.classload.FT");
        Field[] f = clazz.getFields();
        for(Field fd : f) {
            System.out.println(fd.getName() + " | " + fd.getType() + " | " + fd.getModifiers() + " | " + fd.get(""));
        }

    }

}

class FT{
    public static String name = "name";
    public static int age = 11;
}
时间: 2024-10-12 15:38:09

java基础知识(十一)java反射机制(上)的相关文章

Java基础知识——类装载器与反射机制

类装载器ClassLoader 类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件. 类装载器把一个类装入JVM中,要经过三步: 1.装载:查找和导入Class文件: 2.链接:执行校验.准备和解析(解析是可以选择的): 3.初始化:对类的静态变量.静态代码块执行初始化工作: 类装载工作由ClassLoader及其子类负责.JVM在运行时会产生三个ClassLoader:根装载器.ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器). 根装

java基础知识《JAVA 核心技术》学习笔记(一)

一:数据类型 (1)java整形: 类型                         存储要求 int                              4字节 short                          2字节 long                           8字节 byte                           1字节 (2)浮点类型 类型                         储存要求 float            

java基础知识十一

第十一章 类继承 子类继承了父类中可访问的数据域和方法,子类也可添加新的数据域和方法,子类不继承父类的构造函数.一个子类只能有一个直接父类:单继承. 构造顺序 当第1次创建子类对象时,首先初始化其父类静态成员变量(如果没有父类对象实例化过),然后初始化当前子类对象的静态成员变量.注意:第1次之后创建子类对象时,不会再次初始化父类和子类的静态成员变量.其实静态成员变量在有任何实例对象之前已经存在.接着执行该子类对象的父类(若未定义父类,则一定是Object)的构造函数super(-),可能是编译为

java基础之--反射机制

反射的概念: 反射是指程序可以访问.检测和修改它本身的状态和形为的一种能力,并根据自身形为的状态和结果,调整和修改程序所描述的形为的状态和相关语义.                反射是java中一强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以在运行时装配,无须在组件之间进行源码链接.但反射使用不当会使成本很高. 反射的作用: 反编译:.class-->.java 通过反射机制访问java对象的属性,方法,构造方法等: sun为我们提供的反射机制的类: java.lang.Class

Java基础知识:Java知识简介

一.java基础语法: 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种:行为有:摇尾巴.叫.吃等: 类:类是一个模板,它描述一类对象的行为和状态. 方法:方法就是行为,一个类可以有很多方法.逻辑运算.数据修改以及所有动作都是在方法中完成的. 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定. 编写J

《java基础知识》Java异常处理详解

1. Java 中的异常 前言:Java 中的异常处理是处理程序运行错误时的强大机制之一,它可以保证应用程序的正常流程. 首先我们将了解java异常.异常的类型以及受查和非受查异常之间的区别. 1.1 什么是异常? 字面意义:异常是一种不正常的情况. 在 java 中,异常是扰乱程序正常流程的事件,它是在程序运行时抛出的对象. 1.2 什么是异常处理? 异常处理一种在运行时解决程序错误的机制,例如 ClassNotFound.IO.SQL.Remote 等. 1.2.1 异常处理的优势 异常通常

《java基础知识》Java IO流详解

Java IO概念 1. 用于设备之间的数据传输. 2. Java 将操作数据流的功能封装到了IO包中. 3. 数据流流向分:输入流和输出流,操作对象为文件. 4. 流按照操作数据分:字节流(通用)和字符流. 5. 将计算机语言:二进制数据转换成文件显示到电脑上. IO包:继承关系图: 字符流: Reader :读取字符流,方法见API. Writer :写入字符流,方法见API. 案例(Writer ): import java.io.*; public class var { public

《java基础知识》Java集合(Collection)

作为一个Developer,Java集合类是我们在工作中运用最多的.最频繁的类.相比于数组(Array)来说,集合类的长度可变,更加适合于现代开发需求: Java集合就像一个容器,可以存储任何类型的数据,也可以结合泛型来存储具体的类型对象.在程序运行时,Java集合可以动态的进行扩展,随着元素的增加而扩大.在Java中,集合类通常存在于java.util包中. Java集合主要由2大体系构成,分别是Collection体系和Map体系,其中Collection和Map分别是2大体系中的顶层接口.

《java基础知识》Java集合(Map)

Java集合主要由2大体系构成,分别是Collection体系和Map体系,其中Collection和Map分别是2大体系中的顶层接口. 今天主要讲:Map主要有二个子接口,分别为HashMap.TreeMap. 继承关系图: Map的整体特点: 1. 键值对存放<key , value> 2. 遍历需要使用迭代器:Iterator 常用Map HashMap import java.util.HashMap; import java.util.Map; public class var {

JAVA基础知识之JVM-——使用反射生成并操作对象

Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法:可以获取构造器,由Constructor对象表示,调用Constructor对象的newInstance方法可以执行类对应的构造方法:可以获取成员变量,由Field对象表示,通过Field对象可以直接修改类的成员变量的访问权限和值. 创建对象 通过反射有两种方式创建对象 使用Class对象的newInstance(),这是最常用的方式,根据配置文件信息创建对象. 使用Class对象获取指定