IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java反射机制入门 -> 正文阅读

[Java知识库]Java反射机制入门

1.反射机制介绍

1.1编译期是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。

1.2运行期是,直把编译后的文件交给计算机执行到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。

1.3Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。(简单来说,反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。)

1.1.4Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。

1.1.5如果要想知道一个类的属性和方法,必须先获取到该类的字节码文件对象。获取类的信息时,使用的就是 Class 类中的方法。所以先要获取到每一个字节码文件(.class)对应的 Class 类型的对象.众所周知,所有 Java 类均继承了 Object 类,在 Object 类中定义了一个 getClass() 方法,该方法返回同一个类型为 Class 的对象。例如,下面的示例代码:

//方式1 还未装载到内存,获取信息依然是父类对象信息

Class<? extends Class> c = Student.class.getClass();

//方式2 获取类的Class

Student stu = new Student();

Class<? extends Student> stu_class = stu.getClass();

//方式3 获取类的Class

Class<?> c1 = Class.forName("com.qst.test.Student");

1.6利用 Class 类的对象 stu可以访问 Student对象的描述信息、Student类的信息以及基类 Object 的信息

untitled.png

2.1反射机制的优缺点

优点:

  • 能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
  • 与 Java 动态编译相结合,可以实现无比强大的功能。
  • 对于 Java 这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配。

缺点:

  • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
  • 反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。

Java 反射机制在一般的 Java 应用开发中很少使用,即便是 Java EE 阶段也很少使用,但所有的框架底层确大量的使用。

2.2反射机制API

实现 Java 反射机制的类都位于 java.lang.reflect 包中,java.lang.Class 类是 Java 反射机制 API 中的核心类。

2.3java.lang.Class类

java.lang.Class 类是实现反射的关键所在,Class 类的一个实例表示 Java 的一种数据类型,包括类、接口、枚举、注解、数组、基本数据类型和 void。Class 没有公有的构造方法,Class 实例是由 JVM 在类加载时自动创建的。

2.4java.lang.reflect

java.lang.reflect包提供了反射中用到类,主要的类说明如下:

  • Constructor 类:提供类的构造方法信息。
  • Field 类:提供类或接口中成员变量信息。
  • Method 类:提供类或接口成员方法信息。
  • Array 类:提供了动态创建和访问 Java 数组的方法。
  • Modifier 类:提供类和成员访问修饰符信息

3.通过反射访问构造方法

一般情况我们可以通过反射获取构造信息,并且可以通过反射实例化对象

方法:

  • getConstructors() //默认返回公共构造,包括父类或者父接口中
  • getConstructor(Class<?>…parameterTypes)//获取指定公开构造
  • getDeclaredConstructors() //返回所有声明构造包含private? 只获取本类
  • getDeclaredConstructor(Class<?>...parameterTypes)//获取指定任何构造

案例使用类

package com.qst.reflectsss;

public class Apple {

? ? private String color;

? ? public int price;

? ? public Apple() {

? ? }

? ? private Apple(String color) {

? ? ? ? this.color = color;

? ? }

? ? private Apple(int price) {

? ? ? ? this.price = price;

? ? }

? ? public Apple(String color, int price) {

? ? ? ? this.color = color;

? ? ? ? this.price = price;

? ? }

? ? //number对象转换成一个字符串,并返回结果
? ?@Override
? ?public String toString() {

? ? ? ? return "Apple{" +

? ? ? ? ? ? ? ? "color='" + color + '\'' +

? ? ? ? ? ? ? ? ", price=" + price +

? ? ? ? ? ? ? ? '}';

? ? }

}

案例测试代码

package com.qst.reflectsss;

import java.lang.reflect.Constructor;

public class AppleTest {

? ? public static void main(String[] args) throws Exception {

? ? ? ? //读取字节码类
? ? ? ?Class<?> c = Class.forName("com.qst.reflectsss.Apple");

? ? ? ? //读取构造方法 - 只获取公开的构造
? ? ? ?Constructor<?>[] constructors = c.getConstructors();

? ? ? ? for (Constructor cr:constructors) {

? ? ? ? ? ? System.out.println("获取公开的构造:"+cr);

? ? ? ? }

? ? ? ? System.out.println("============================================");

? ? ? ? //获取所有的构造
? ? ? ?Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();

? ? ? ? for (Constructor cr:declaredConstructors) {

? ? ? ? ? ? System.out.println("获取所有的构造:"+cr);

? ? ? ? }

? ? ? ??

? ? ? ? System.out.println("=============================================");

? ? ? ? //获取空的
? ? ? ?Constructor<?> constructor = c.getConstructor();

? ? ? ? System.out.println("获取空构造:"+constructor);

? ? ? ? System.out.println("=============================================");

? ? ? ? //获取有参的
? ? ? ?Constructor<?> constructor1 = c.getConstructor(String.class,int.class);

? ? ? ? System.out.println("获取有参构造:"+constructor1);

? ? ? ? System.out.println("=============================================");

? ? ? ? //测试使用getConstructor获取私有的构造 ? -- ?不可以
? ? ? ?/*Constructor<?> constructor2 = c.getConstructor(String.class);
? ? ? ?System.out.println(constructor2);*/

? ? ? ?//测试使用getDeclaredConstructor获取私有的构造
? ? ? ?Constructor<?> constructor3 = c.getDeclaredConstructor(int.class);

? ? ? ? System.out.println("获取私有构造:"+constructor3);

? ? ? ? System.out.println("=============================================");

? ? ? ? //实例化对象 ?== ?公开的空构造
? ? ? ?Constructor<?> constructor4 = c.getConstructor();

? ? ? ? Apple app = (Apple)constructor4.newInstance();

? ? ? ? System.out.println("获取公开构造:"+app);//输出内存地址

? ? ? ?System.out.println("=============================================");

? ? ? ? //实例化对象 ?== ?公开的有参构造);
? ? ? ?Constructor<?> constructor5 = c.getConstructor(String.class,int.class);

? ? ? ? Apple app1 = (Apple)constructor5.newInstance("红富士",5);

? ? ? ? System.out.println("获取公开的有参构造:"+app1);

? ? ? ? System.out.println("=============================================");

? ? ? ? //实例化对象 ?== ?私有的有参构造
? ? ? ?Constructor<?> constructor6 = c.getDeclaredConstructor(String.class);

? ? ? ? //暴力反射 ?== ?授权允许操作私有的
? ? ? ?constructor6.setAccessible(true);

? ? ? ? Apple app2 = (Apple)constructor6.newInstance("红富士");

? ? ? ? System.out.println("获取私有的有参构造:"+app2);

? ? }

}

4.通过反射访问方法

方法:

  • getMethods()
  • getMethods(String name,Class<?> …parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethods(String name,Class<?>...parameterTypes)

案例使用类

package com.qst.reflectsss;

/*
* 测试反射方法
*
* */

public class Cat {

? ? public Cat() {

? ? }

? ? //测试方法
? ?public void eat(){

? ? ? ? System.out.println("猫吃鱼");

? ? }

? ? void run(){

? ? ? ? System.out.println("猫在奔跑");

? ? }

? ? protected String sleep(){

? ? ? ? return "猫爱睡觉";

? ? }

? ? private String ww(){

? ? ? ? return "ww";

? ? }

}

案例测试代码

package com.qst.reflectsss;

import java.lang.reflect.Method;

public class CatTest {

? ? public static void main(String[] args) throws Exception {

? ? ? ? //字节码类
? ? ? ?Class<?> c = Class.forName("com.qst.reflectsss.Cat");

? ? ? ? //创建对象:获取方法时用不上,但执行方法的时候一定用得上
? ? ? ?Cat cat = (Cat)c.newInstance();

? ? ? ? //读取公开的方法 ?-- ?可以读取父类的公开方法
? ? ? ?Method[] methods = c.getMethods();

? ? ? ? for (Method m: methods) {

? ? ? ? ? ? System.out.println("读取公开的方法:"+m);

? ? ? ? }

? ? ? ? System.out.println("====================================");

? ? ? ? //读取所有方法 ?-- ?只能读取本类所有方法
? ? ? ?Method[] declaredMethods = c.getDeclaredMethods();

? ? ? ? for (Method m:declaredMethods) {

? ? ? ? ? ? System.out.println("读取所有方法:"+m);

? ? ? ? }

? ? ? ? System.out.println("====================================");

? ? ? ? //读取单个方法 -- 读取公开的
? ? ? ?Method eat = c.getMethod("eat");

? ? ? ? System.out.println("读取eat方法:"+eat);

? ? ? ? System.out.println("====================================");

? ? ? ? //读取不公开的方法
? ? ? ?Method run = c.getDeclaredMethod("run");

? ? ? ? Method sleep = c.getDeclaredMethod("sleep");

? ? ? ? Method ww = c.getDeclaredMethod("ww");

? ? ? ? System.out.println("读取不公开方法:"+run);

? ? ? ? System.out.println("读取不公开方法:"+sleep);

? ? ? ? System.out.println("读取不公开方法:"+ww);

? ? ? ? System.out.println("=================测试方法执行==============");

? ? ? ? //测试无返回值,公开的
? ? ? ?Object invoke = eat.invoke(cat);

? ? ? ? System.out.println("测试公开无返回值的:"+invoke);

? ? ? ? //测试有返回值,且不公开的
? ? ? ?Object invoke1 = sleep.invoke(cat);

? ? ? ? System.out.println("测试不公开有返回值的:"+invoke1);

? ? ? ? //私有的方法,一定需要设置反射权限,暴力反射
? ? ? ? ww.setAccessible(true);

? ? ? ? Object invoke2 = ww.invoke(cat);

? ? ? ? System.out.println("测试不公开有返回值的:"+invoke2);

? ? ? ? Object invoke3 = run.invoke(cat);

? ? ? ? System.out.println("测试不公开有返回值的:"+invoke3);

? ? }

}

5.通过反射访问属性

方法:

  • getFields()
  • getField(String name)
  • getDeclaredFields()
  • getDeclaredField(String name)

案例使用类

package com.qst.reflectsss;

public class Dog {

? ? public String name;

? ? int age;

? ? public String color;

? ? public String eat;

? ? public Dog() {

? ? }

? ? public String getName() {

? ? ? ? return name;

? ? }

? ? public void setName(String name) {

? ? ? ? this.name = name;

? ? }

? ? public int getAge() {

? ? ? ? return age;

? ? }

? ? public void setAge(int age) {

? ? ? ? this.age = age;

? ? }

? ? public String getColor() {

? ? ? ? return color;

? ? }

? ? public void setColor(String color) {

? ? ? ? this.color = color;

? ? }

? ? public String getEat() {

? ? ? ? return eat;

? ? }

? ? public void setEat(String eat) {

? ? ? ? this.eat = eat;

? ? }

? ? @Override
? ?public String toString() {

? ? ? ? return "Dog{" +

? ? ? ? ? ? ? ? "name='" + name + '\'' +

? ? ? ? ? ? ? ? ", age=" + age +

? ? ? ? ? ? ? ? ", color='" + color + '\'' +

? ? ? ? ? ? ? ? ", eat='" + eat + '\'' +

? ? ? ? ? ? ? ? '}';

? ? }

}

案例测试代码

package com.qst.reflectsss;

import java.lang.reflect.Field;

public class DogTest {

? ? public static void main(String[] args) throws Exception {

? ? ? ? Class<?> c = Class.forName("com.qst.reflectsss.Dog");

? ? ? ? Dog dog = (Dog)c.newInstance();

? ? ? ? //获取公开的属性信息
? ? ? ?Field[] fields = c.getFields();

? ? ? ? for (Field f :fields) {

? ? ? ? ? ? System.out.println("获取公开的属性信息:"+f);

? ? ? ? }

? ? ? ? System.out.println("====================================");

? ? ? ? //获取所有的属性信息
? ? ? ?Field[] declaredFields = c.getDeclaredFields();

? ? ? ? for (Field f:declaredFields) {

? ? ? ? ? ? System.out.println("获取所有的属性信息:"+f);

? ? ? ? }

? ? ? ? System.out.println("====================================");

? ? ? ? //获取单个的属性信息
? ? ? ?Field name= c.getField("name");

? ? ? ? System.out.println("获取单个的属性信息:"+name);

? ? ? ? System.out.println("====================================");

? ? ? ? //获取单个非公开的属性
? ? ? ?Field age = c.getDeclaredField("age");

? ? ? ? System.out.println("获取单个非公开的属性:"+age);

? ? ? ? Field eat = c.getDeclaredField("eat");

? ? ? ? System.out.println("获取单个非公开的属性"+eat);

? ? ? ? System.out.println("====================================");

? ? ? ? //取值与赋值
? ? ? ?name.set(dog,"来福");

? ? ? ?/* dog.setName("来福");
? ? ? ?dog.setColor("啃骨头");*/
? ? ? ?age.set(dog,22);

? ? ? ? dog.setColor("大黄");

? ? ? ? eat.set(dog,"啃骨头");

? ? ? ? System.out.println("查看赋值操作:"+dog);

? ? ? ? Object o = name.get(dog);

? ? ? ? System.out.println("通过反射取值:"+o);

? ? }

}

6.newInstance()和new()区别

1、两者创建对象的方式不同,前者是实用类的加载机制,后者则是直接创建一个类:

2、newInstance创建类是这个类必须已经加载过且已经连接,new创建类是则不需要这个类加载过

3、newInstance: 弱类型(GC是回收对象的限制条件很低,容易被回收)、低效率、只能调用无参构造,new 强类型(GC不会自动回收,只有所有的指向对象的引用被移除是才会被回收,若对象生命周期已经结束,但引用没有被移除,经常会出现内存溢出)

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 07:36:16  更:2021-07-28 07:37:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 14:20:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码