在我们使用形如 ClassName object = new ClassName(); 的语句进行创建实例的时候,我们默认 ClassName 已经在系统内存在的了,所以直接使用new 的方式进行创建。
事实上,在启动虚拟机的时候,我们定义在系统内的类通过类的加载器(class loader)加载到系统内。所以当系统运行的时候,我们就可以使用该类。
有时候,在系统运行的时候,类并没有存在在系统内,我们需要手动加载类文件到系统内,然后再使用它(创建对象或者使用其类方法等等)。
类的加载
在运行时期加载类,是通过 JVM 内的Class对象 的 Class.forName()方法将类定义加载到系统内,返回一个对应的类文件的表示对象。
例如,创建一个Animal的类,然后通过手动加载到内存中,代码如下:
- package com.lou;
- public abstract class Animal {
- private Integer age;
- private double weight;
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- public double getWeight() {
- return weight;
- }
- public void setWeight(double weight) {
- this.weight = weight;
- }
- public abstract void walk();
- }
- package com.lou;
- public class Client {
- public static void main(String[] args) {
- try {
- Class clazz = Class.forName("com.lou.Animal");
- System.out.println("成功加载类文件 "+clazz.getSimpleName());
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- }
一个class 定义有什么? 对应的class 对象有哪些组件?
我们定义一个Java 类,基本上会具有:注解(Annotation),成员字段(Field),Constructor(构造器),方法(Method),定义的内部类,自己的父类,实现的接口等。
构造器(Constructor)及使用Class 对象创建 实例对象
构造器的作用就是创建对象。一般创建构造器时,会有相应的描述符:public private 等;参数列表;抛出的异常信息。
我们通过Class 对象取得构造器对象时,要提供相应的构造器的参数列表。参数列表构造器的"id",每个构造器都不一样。如果提供没有定义过的参数列表,将会抛出异常。
构造器的价值就是用于创建出实例对象和初始化。使用 构造器的 newInstance(Object ... varArgs) 方法可以创建出一个实例对象。不过该方法返回的是Object 对象,要根据相应的Class对象向下转型。
如下面所示的例子,获取Worker 的构造器对象,并且创建对象
- package com.lou;
- import java.math.BigDecimal;
- public class Worker {
- public String id;//工号
- public String name;//姓名
- public BigDecimal salary;//工资
- private Worker()
- {
- }
- public Worker(String id,String name)
- {
- this.id = id;
- this.name = name;
- }
- public Worker(String id,String name,BigDecimal salary)
- {
- this(id,name);
- this.salary = salary;
- }
- public void work()
- {
- System.out.println("Working......");
- }
- }
- package com.lou;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
- public class Client1 {
- public static void main(String[] args) {
- try {
- Class clazz = Class.forName("com.lou.Worker");
- System.out.println("成功加载类文件 "+clazz.getSimpleName());
- //返回clazz 的公共构造器
- Constructor[] constructors = clazz.getConstructors();
- System.out.println("公共构造器共有 "+ constructors.length +" 个。");
- System.out.println("它们分别是:");
- for(Constructor cons : constructors)
- {
- System.out.println(cons.toGenericString());
- }
- //返回clazz 的指定公共构造器
- Constructor constructor = clazz.getConstructor(String.class,String.class);
- //通过newInstance(Object ...varArgs) 创建对象
- Worker worker=(Worker)constructor.newInstance(new String("1234"),new String("louis"));
- System.out.println(worker.id);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
成员字段(Field)及其操作
Field 域作为字段域,可以获取其 修饰符,字段的类型,还有变量名;通过field对象,可以设置和某个 实例对象对应的字段的值。
以上面的Worker类为例,获取和设置其实例对象的值:
- package com.lou;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.math.BigDecimal;
- public class Client1 {
- public static void main(String[] args) {
- try {
- Class clazz = Class.forName("com.lou.Worker");
- System.out.println("成功加载类文件 "+clazz.getSimpleName());
- // 获取指定名称的可访问的field
- Field field = clazz.getField("id");
- System.out.println("Field " + field.getName() +"获取成功。");
- Object o = clazz.getConstructor(String.class,String.class,BigDecimal.class).newInstance(new String("123"),new String("louis"),new BigDecimal(23));
- // 取出对象内对应字段的值
- String value = (String) field.get(o);
- System.out.println("对象对应字段的值是:"+ value);
- // 设置某个对象内对应字段的值
- field.set(o, "321");
- System.out.println("对象对应的字段的值被设定为:"+field.get(o));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
Method 及其相关操作
Method 对象代表类内的某个方法,可以获取其修饰符、返回的数据类型、方法名、抛出的异常类型、触发某个实例对象的这个方法。
- package com.lou;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.math.BigDecimal;
- public class Client1 {
- public static void main(String[] args) {
- try {
- Class clazz = Class.forName("com.lou.Worker");
- System.out.println("成功加载类文件 "+clazz.getSimpleName());
- // 获取指定名称的可访问的field
- Field field = clazz.getField("id");
- System.out.println("Field " + field.getName() +"获取成功。");
- Object o = clazz.getConstructor(String.class,String.class,BigDecimal.class).newInstance(new String("123"),new String("louis"),new BigDecimal(23));
- // 获取类的某个可访问的方法:
- Method method = clazz.getMethod("work", null);
- System.out.println("Method " + method.getName() +"获取成功。");
- // 触发调用Worker类对应的方法
- method.invoke(o, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
附录:一个完整的例子:
一个Human 类继承自 抽象类Animal,实现接口Inventor,并且其上有注解 Author 和Function,现在通过以下的代码对Human类进行解析:
- package com.lou;
- @Author(id = "4321",name ="luan",date="2014")
- public abstract class Animal {
- private Integer age;
- private double weight;
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- public double getWeight() {
- return weight;
- }
- public void setWeight(double weight) {
- this.weight = weight;
- }
- public abstract void walk();
- }
- package com.lou;
- public interface Inventor {
- // 发明者的实现方法
- public void invent();
- }
- package com.lou;
- // 注解区域
- @Author(id = "1234",name ="louis",date="2014")
- @Function(value ="人类的类定义")
- public class Human extends Animal implements Inventor{
- //成员变量区 Fields
- private String name;
- private String color;
- private String nationality;
- public String birthDate;
- // 构造器部分 Constructor
- public Human()
- {
- }
- private Human(String name)
- {
- this.name= name;
- }
- @Function(value = "构造器,带有三个参数")
- public Human(String name,String color,String nationality) throws Exception
- {
- this(name);
- this.color = color;
- this.nationality = nationality;
- }
- public Human(String name,String color,String nationality,String birthDate) throws Exception
- {
- this(name,color,nationality);
- this.birthDate = birthDate;
- }
- //方法区域
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getColor() {
- return color;
- }
- public void setColor(String color) {
- this.color = color;
- }
- @Override
- public void invent() {
- System.out.println("人类发明。。。。。");
- }
- @Override
- public void walk() {
- System.out.println("Using two legs");
- }
- @Author(id = "123",name ="luan",date="2014")
- public void speak()
- {
- System.out.println("You are in "+ nationality +",You can speak "+nationality);
- }
- class Mind{}
- }
- package com.lou;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- // 对书写的类或者方法进行标识
- @Retention(value=RetentionPolicy.RUNTIME)
- public @interface Author {
- public String id() default "none";
- public String name() default "none";
- public String date();
- }
- package com.lou;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- // 功能描述
- @Retention(value=RetentionPolicy.RUNTIME)
- @interface Function {
- public String value() default "none";
- }
Client 类的方法内对 Human 的 Annotation,Constructor,Field,Method 相关的操作进行了细致的示范。
- package com.lou;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.lang.reflect.Type;
- public class Client {
- public static void main(String[] args) throws Exception {
- // 注解操作
- annotationsOperations();
- //构造器操作
- constructorOperations();
- //字段操作
- fieldOperations();
- //方法操作
- methodOperations();
- }
- /*
- * 注解相关 操作
- */
- private static void annotationsOperations() {
- Class clazz = Human.class;
- // 如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。
- Author author = (Author) clazz.getAnnotation(Author.class);
- System.out.println("这个类的作者是:" + author.name());
- // 获取运用到当前class 上的所有 注解
- Annotation[] annotations = clazz.getDeclaredAnnotations();
- // Annotation[] annotations = clazz.getAnnotations();
- System.out.println("Class " + clazz.getSimpleName() + " has "
- + annotations.length + " annotations。");
- }
- /*
- * 构造器操作
- */
- private static void constructorOperations() throws SecurityException,
- NoSuchMethodException, IllegalArgumentException,
- InstantiationException, IllegalAccessException,
- InvocationTargetException {
- Class clazz = Human.class;
- /*
- * Constructor<T> getConstructor(Class<?>... parameterTypes) 返回一个
- * Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
- */
- Constructor constructor = clazz.getConstructor(null);// 无参构造器
- Constructor constructor2 = clazz.getConstructor(String.class,
- String.class, String.class); // 三个个String 类型的参数构造器
- /*
- * Constructor<?>[] getConstructors() 返回一个包含某些 Constructor 对象的数组,这些对象反映此
- * Class 对象所表示的类的所有公共构造方法。
- */
- Constructor[] cons = clazz.getConstructors();
- System.out.println("公共构造器数量为:" + cons.length);
- /*
- * Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- * 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
- * 这个可以得到所有在这个类内定义的构造器,不管是不是public 的
- */
- Constructor[] constructs = clazz.getDeclaredConstructors();
- System.out.println("公共构造器数量为:" + constructs.length);
- Constructor cons2 = clazz.getDeclaredConstructor(String.class,
- String.class, String.class);
- /*
- * 构造器上的注解
- */
- Annotation[] annos = cons2.getAnnotations();
- System.out.println("此构造器上的注解个数为:" + annos.length);
- Function function = (Function) cons2.getAnnotation(Function.class);
- System.out.println("Function 注解:" + function.value());
- /*
- * 获取此构造器抛出来的异常信息
- */
- Class[] exceptions = cons2.getExceptionTypes();
- System.out.println("-----构造器抛出来的异常共有:" + exceptions.length
- + "个。如下:----");
- for (Class c : exceptions) {
- System.out.println(c.getSimpleName());
- }
- /*
- * Type[] getGenericExceptionTypes() 返回一组 Type 对象,这些对象表示声明要由此
- * Constructor 对象抛出的异常
- */
- System.out.println("----------构造器的Generic Exception Types-----------");
- Type[] types = cons2.getGenericExceptionTypes();
- for (Type t : types) {
- System.out.println(t.toString());
- }
- /*
- * Type[] getGenericParameterTypes() 按照声明顺序返回一组 Type 对象,这些对象表示此
- * Constructor 对象所表示的方法的形参类型。
- */
- System.out.println("------构造器方法形参的数据类型数组为:-------------");
- Type[] types2 = cons2.getGenericParameterTypes();
- for (Type t : types2) {
- System.out.println(t.toString());
- }
- /*
- * Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此
- * Constructor 对象所表示构造方法的形参类型。
- */
- /*
- * public int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java
- * 语言修饰符。应该使用 Modifier 类对这些修饰符进行解码。
- */
- System.out.println("---------构造器的修饰符是:-----------");
- System.out.println(cons2.getModifiers());
- if (Modifier.isPublic(cons2.getModifiers())) {
- System.out.println("Modifier is public ");
- }
- /*
- * String getName() 以字符串形式返回此构造方法的名称。
- */
- String constructorName = cons2.getName();
- System.out.println("------此构造器的名称是:" + constructorName);
- /*
- * Class<T> getDeclaringClass() 返回 Class 对象,该对象表示声明由此 Constructor
- * 对象表示的构造方法的类。 即返回这个构造器所在的类
- */
- Class parent = cons2.getDeclaringClass();
- System.out.println("----------此构造器所在的类是:");
- System.out.println(parent.getCanonicalName());
- /*
- * boolean isVarArgs() 如果声明此构造方法可以带可变数量的参数,则返回 true;否则返回 false。
- */
- System.out.println("参数列表是否支持可变变量:" + cons2.isVarArgs());
- /*
- * 通过constructor对象创建对象 T newInstance(Object... initargs)
- */
- Human human = (Human) cons2.newInstance(new String("louis"),
- new String("yellow"), new String("nationality"));
- System.out.println("Human's name is " + human.getName());
- }
- /*
- * Field 相关操作
- */
- private static void fieldOperations() throws Exception
- {
- Class clazz = Human.class;
- //获取类内定义的所有成员字段,返回一个数组,包括私有成员字段
- Field[] fields = clazz.getDeclaredFields();
- System.out.println(clazz.getSimpleName()+" 定义的成员字段共有:"+fields.length);
- //获取类内定义的 指定名称的成员字段 包括私有成员字段
- Field field = clazz.getDeclaredField("name");
- //返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
- //包括从父类继承过来的可访问的字段
- Field[] fields1 = clazz.getFields();
- //返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
- //包括从父类继承过来的可访问的字段
- Field field2 = clazz.getField("birthDate");
- Human human = new Human("lou","yellow","China","1991-10");
- /*
- * 获取human对象的对应字段的值
- * Object get(Object obj)
- * XXX getXXX(Object obj) XXX Boolean,Byte,Char,Double,Long,Float,Int,Short 等
- */
- Object value = field2.get(human);
- System.out.println("human对应字段 " + field2.getName() +" 的值为:"+value);
- /*
- * 设置human对象的对应字段的值
- * void set(Object obj, Object value)
- * void setXXX(Object obj, XXX z) XXX Boolean,Byte,Char,Double,Long,Float,Int,Short 等
- */
- field2.set(human, "1990-1");
- System.out.println("human 对象的值已经被设定为:"+field2.get(human));
- /*
- * 获取成员字段的数据类型
- * Class<?> getType()
- * Type getGenericType()
- */
- Class type = field2.getType();
- System.out.println("字段"+field2.getName()+" 的类型是:"+type.getName());
- }
- /*
- * Method 相关操作
- */
- private static void methodOperations() throws Exception
- {
- Class clazz = Human.class;
- //返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
- Method[] methods = clazz.getMethods();
- //返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
- Method method = clazz.getMethod("speak", null);
- //返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
- Method[] methods2 = clazz.getDeclaredMethods();
- //返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
- Method method2 = clazz.getDeclaredMethod("walk", null);
- /*
- * Object invoke(Object obj, Object... args)
- * 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
- * 调用某个对象的这个方法
- */
- Human human = new Human("lou","yellow","China","1991-10");
- method2.invoke(human, null);
- }
- }
相关推荐
java反射机制java反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制.zipjava反射机制...
Java反射机制是Java编程语言中的一个强大工具,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者能够在运行时动态地获取类的信息(如类名、方法名、参数类型)并调用方法,创建对象,甚至...
JAVA反射机制应用 JAVA反射机制是JAVA语言中的一种动态机制,它能够在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。这种动态获取的信息以及动态...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息。通过Java反射机制,开发者可以在不知道具体类名的情况下创建对象,调用方法,访问和修改私有成员变量,以及...
Java反射机制是Java编程语言中的一个重要特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类集中在java.lang.reflect包下,包括Class、Constructor、Method和...
### Java反射机制深入理解 #### 一、反射机制概述 Java反射机制是一种强大的工具,它允许程序在运行时检查和操作任何类、方法、构造函数和字段等元素。这种能力对于构建灵活的应用程序和框架非常有用,特别是那些...
Java反射机制是Java语言提供的一种强大工具,它允许在程序运行时动态地获取类的信息以及对类的对象进行操作。在Java中,静态编译时类型检查确保了代码的稳定性,但有时我们需要在运行时根据需求动态地创建对象、调用...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者可以动态地获取类的信息并调用其方法,创建对象,访问私有成员,甚至改变类的行为。在深入...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取和操作任何已知名称的类的内部信息。这一机制使得Java具备了一定的动态性,虽然在传统的分类中Java被视为静态类型语言。通过反射,开发者可以在...
Java 反射机制是 Java 语言中的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并调用对象的方法,甚至修改对象的状态。这一机制极大地增强了 Java 程序的灵活性和可扩展性,尤其是在...
这篇博文"Java反射机制学习(二)"可能深入探讨了如何利用反射进行动态类型处理、访问私有成员以及创建对象等核心概念。在这里,我们将详细讨论Java反射的基本用法及其在实际开发中的应用。 1. **什么是反射**: ...
java反射机制和动态代理的原理,熟悉反射机制和动态代理
### Java反射机制详解 #### 一、Java反射机制概述 Java反射机制是Java语言的一个重要特性,它允许程序在运行时获取类的信息并操作对象。Java反射机制的主要作用包括:获取类的所有属性和方法、构造动态实例、调用...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类的对象。这种机制使得Java具有高度的灵活性和动态性,可以在编译时未知类的情况下进行类的加载、实例化、方法调用等操作...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息。这个特性使得Java具备了高度的灵活性,能够在运行时动态地发现和使用类的属性和方法,即使这些信息在编译时...
Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查并操作类、接口、字段和方法的信息,打破了通常编译时静态绑定的限制。通过反射,我们可以动态地创建对象,调用方法,访问和修改字段值,甚至...
### Java反射机制详解 #### 一、引言 在Java面试中,经常会出现与反射机制相关的题目。这是因为Java反射机制不仅是Java语言的一项重要特性,也是理解Java动态特性的关键所在。通过本文,我们将深入探讨Java反射...
java反射机制核心代码,小弟一直弄不明白,怎么通过反射来调用私有成员方法,看了这个后,你可以随心调用private方法,和属性,记得添加setAccessable(true),哦,要不还是不行,如:method.setAccessable(true);
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并进行操作。通过反射,开发者可以在程序执行时发现并访问类的字段(fields)、方法(methods)以及构造器(constructors),...