首页 > 编程语言 >JAVA基础-反射

JAVA基础-反射

时间:2024-02-19 10:46:53浏览次数:27  
标签:aClass p1 JAVA 反射 获取 基础 Person class 属性

1,什么是反射?

  Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

2,反射的作用

  我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

3,反射的具体实现

3.1 获取到 Class 三种方式。

//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
//  类型的对象,而我不知道你具体是什么类,用这种方法
  Person p1 = new Person();
  Class c1 = p1.getClass();

//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
//  这说明任何一个类都有一个隐含的静态成员变量 class
  Class c2 = Person.class;

//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
//   但可能抛出 ClassNotFoundException 异常
  Class c3 = Class.forName("com.ys.reflex.Person");

需要注意的是:一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1,c2,c3进行 equals 比较,发现都是true

3.2 获取包名/类名等

Person aClass = Person.class;

aClass.getPackage().getName();
aClass.getSimpleName();
aClass.getName();
aClass.getTypeName();
aClass.getCanonicalName();

3.3 反射构建对象

Person aClass = Person.class;

Person person = aClass.newInstance();

这里必须有无参构造方法

3.4 构造方法

Person aClass = Person.class;

//获取所有 public 构造方法
aClass.getConstructors();
        
//获取无参构造方法
aClass.getConstructor();

//获取指定参数列表的构造方法        
Constructor<? extends Person> constructor = aClass.getConstructor(String.class, int.class);

//使用构造方法构造对象
Person p1 = constructor.newInstance("张三", 10);

3.5 属性

 Person aClass = Person.class;
 Person p1 = new Person();

 //获取指定属性
 Field field = aClass.getDeclaredField("name");
 
 //破坏属性 private,protected 等权限设置
 field.setAccessible(true);
 
 //获取 p1 对象的属性值
 System.out.println( field.get(p1) );

 //个 p1 对象的属性赋值
 field.set(p1, "李四");

 System.out.println(field.get(p1));

 Field num = aClass.getDeclaredField("num");

 //获取静态属性 num 的值
 System.out.println(num.get(null));
 num.set(null,10);
 
//静态属性值获取同样可以通过对象,也可以用 null
 System.out.println(num.get(null));
 System.out.println(num.get(p1));
 num.set(person,20);

 //静态属性值设置可以通过 null 来表示,也可以通过对象
 System.out.println(num.get(null));
 System.out.println(num.get(p1));
  • getDeclaredFields() 和 getFields() 区别在于,getDeclaredFields() 可以无视 private 等权限设置获取属性,getFields() 只能获取 publice 权限的属性。构造方法,方法和属性都是这个规律。

  • 如果通过 getDeclaredFields() 获取到的属性,需要通过 field.setAccessible(true) 将权限破坏,否则可能在使用的时候抛出权限异常。

  • 静态属性操作可以用 null 表示,通过某个实例也是可以的。

3.6 方法

//获取所有方法
aClass.getMethods();

//获取指定方法,第一个参数是方法名,第二个参数列表类型 Class ...
Method method = aClass.getMethod("run", String.class);

//执行方法,第一个参数对象,第二个参数列表
method.invoke(p1, "北京");

Method staticMethod = aClass.getMethod("staticMethod");

//执行静态方法
staticMethod.invoke(null);

//静态方法也可以通过实例来执行
staticMethod.invoke(p1);

3.7 获取注解

//获取指定类型注解。方法/属性等也有此操作,不再赘述。
Deprecated annotation = aClass.getAnnotation(Deprecated.class);

3.8 判断是否数组

Class aClass = Person.class;
getClass().isArray();

3.9 获取类加载器

aClass.getClassLoader()

3.10 获取父类

Class<?> superclass = aClass.getSuperclass();

标签:aClass,p1,JAVA,反射,获取,基础,Person,class,属性
From: https://www.cnblogs.com/cnff/p/17013576.html

相关文章

  • JAVA基础-泛型
    1,泛型概述泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型......
  • JAVA基础-序列化
    1,什么是序列化?Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。2,序列化的使用场景永久性保存对象,保存对的字节序列到本地文件或者数据库中;通过序列化以字节流的形式对象在网络中进行传递和接收;通过序列化在进程间传递......
  • JAVA基础-Steam
    1,OptionalJava8中的Optional是一个可以包含或不可以包含非空值的容器对象。1.1,获取Optional的三个方法1.of(value)返回一个Optional,value不可以为null2.empty()返回一个空的Optional3.ofNullable(value)返回一个Optional,如果value为null,就是empty(),否......
  • JAVA基础-类加载过程
    1,类的加载1,类的加载过程2,加载阶段通过一个类的全限定名获取定义此类的二进制字节流将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口加载class文件的方式:从本......
  • JAVA基础-jdk8新特性
    Java8新特性:接口默认方法和静态方法JDK1.8打破了接口只提供了形式,而未提供任何具体实现这一限制,允许定义默认方法和静态方法。定义一个接口:packagecom.zgjt.design.defaults;importjava.util.function.Supplier;publicinterfaceAnimal{//接口默认方法,不必重......
  • Java开发的SRM供应商、在线询价、招投标采购一体化系统源码功能解析
    前言:随着全球化和信息化的发展,企业采购管理面临越来越多的挑战。传统的采购方式往往涉及到多个繁琐的步骤,包括供应商筛选、询价、招投标等,这些过程不仅耗时,而且容易出错。为了解决这些问题,供应商、询价、招投标一体化系统应运而生。该系统通过集成供应商管理、询价管理、招投标......
  • Java对象引用和内存管理的细节
    在Java中,当局部变量(比如方法参数)的作用域结束时,这个局部变量的引用确实不再存在,但这并不意味着它引用的对象会被销毁。对象的销毁是由Java的垃圾回收器(GarbageCollector,GC)来管理的。在Java中,局部变量(如方法参数)通常存储在栈内存(StackMemory)中,而对象实例(如ServletConfig对象)则......
  • 关于java代码Runtime.getRuntime().exec()执行shell脚本中的坑
    java操作shell脚本执行docker命令  Runtime.getRuntime().exec()是不能执行特殊符号如">"、"|"等必须通过"/bin/sh""-c"处理。另外java操作docker 不能分配  dockerexec-i(不要t).另外如果不确定脚本是否执行成功,可以通过waitFor返回的int结果,如果为0脚本执行......
  • 提高Java开发生产力,我选Stream API,真香啊
    Java8引入的StreamAPI提供了一种新的数据处理方式,它以声明式、函数式的编程模型,极大地简化了对集合、数组或其他支持数据源的操作。Stream可以被看作是一系列元素的流水线。允许你高效地对大量数据执行复杂的过滤、映射、排序、聚合等操作,而无需显式地使用循环或者临时变量。St......
  • Java注解篇之@SuppressWarnings注解详解 代码编译通过且可以运行,但每行前面的“感叹号
    Java注解篇之@SuppressWarnings注解详解@SuppressWarnings作用:用于抑制编译器产生警告信息。它的注解目标为类、字段、函数、函数入参、构造函数和函数的局部变量,但是建议注解声明在最接近警告发生的位置。去感叹号?我们经常遇到代码编译通过且可以运行,但每行前面的“感叹号”就......