18 Java反射reflect(类加载+获取类对象+通用操作+设计模式+枚举+注解)

news2024/11/17 23:50:25

Java反射

    • 18 反射reflect
      • 18.1 类的加载
      • 18.2 Class对象
      • 18.3 获取类对象的3种方法
      • 18.4 反射通用操作
        • 18.4.1 常见方法
        • 18.4.2 通用操作
      • 18.5 设计模式
        • 18.5.1 概念
        • 18.5.2 好处
        • 18.5.3 工厂设计模式
        • 18.5.4 单例模式
      • 18.6 枚举
      • 18.7 注解
        • 18.7.1 概念
        • 18.7.2 定义注解
        • 18.7.3 注解属性类型
        • 18.7.4 元注解

18 反射reflect

18.1 类的加载

一、类对象


类的对象:基于某个类 new 出来的对象,也称为实例对象。

类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法) 。

注意:每个类加载到内存都会生成一个唯一的类对象。
在这里插入图片描述

在JVM中类的加载是有细分操作,当程序启动时候说那个到某个类,如果该类被加载到内存中,则JVM会通过三个步骤进行类的初始化操作【加载、连接和初始化】
在这里插入图片描述

18.2 Class对象

PS:在Java中提供一个类这个类叫做Class,用于存储类的字节码文件

对象【存储自定义类中描述信息】

因为JVM中是存在Class类对象的,所以Java就提供了另外一种方式,可以直接通过Class类的对象加载出来对应类的对象操作,这个操作就叫做“【反射reflect】”

例如创建Sutdent类

正常创建对象 Student stu = new Student();

但是在JVM中先得到Student类的.class字节码文件,通过字节码文件创建出Student类的对象
在这里插入图片描述

18.3 获取类对象的3种方法


  • 通过类的对象,获取类对象。
Student s = new Student();
Class c = s.getClass();
  • 通过类名获取类对象。
Class c = 类名.class;
  • 通过静态方法获取类对象。
Class c=Class.forName(“包名.类名”);

18.4 反射通用操作


18.4.1 常见方法

方法名描述
public String getName()获取类的完全名称
public Package getPackage()获取包信息
public Class<? super T> getSuperclass()获取父类
public Class<?>[] getInterfaces()获取实现父接口
public Field[] getFields()获取字段信息
public Method[] getMethods()获取方法信息
public Constructor<?>[] getConstructors()获取构造方法
public T newInstance()反射创建对象

18.4.2 通用操作

反射通用操作:使用反射机制获取类对象,并使用Class对象的方法获取表示类成员的各种对象(比如Constructor、Method、Field等),实现反射各种应用。

案例演示:反射操作。

Person类:

public class Person implements Serializable,Cloneable{
	//姓名
	private String name;
	//年龄
	private int age;
	
	public Person() {
		System.out.println("无参构造执行了...");
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		System.out.println("带参构造方法执行了...");
	}


	//吃
	public void eat() {
		System.out.println(name+"正在吃东西......");
	}


	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	//带参的方法
	public void eat(String food) {
		System.out.println(name+"开始吃...."+food);
	}
	
	//私有的方法
	private void privateMethod() {
		System.out.println("这是一个私有方法");
	}
	
	//静态方法
	public static void staticMethod() {
		System.out.println("这是一个静态方法");
	}
}

TestPerson类:

public class TestPerson {
	public static void main(String[] args) throws Exception {
		//调用测试以下方法
        //代码略
	}
	//获取类对象的三种方式
	public static void getClazz() throws Exception {
		//1使用对象获取类对象
		Person zhangsan=new Person();
		Class<?> class1=zhangsan.getClass();
		System.out.println(class1.hashCode());
		//2使用类名.class属性
		Class<?> class2=Person.class;
		System.out.println(class2.hashCode());
		//3使用Class的静态方法[推荐使用]
		Class<?> class3=Class.forName("com.qf.chap17_1.Person");
		System.out.println(class3.hashCode());
	}
	
	//1 使用反射获取类的名字、包名、父类、接口
	public static void reflectOpe1() throws Exception {
		//(1)获取类对象 Person
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//getName();
		System.out.println(class1.getName());
		//getPackage();
		System.out.println(class1.getPackage().getName());
		//getSuperClass();
		System.out.println(class1.getSuperclass().getName());
		//getInterfaces();
		Class<?>[] classes=class1.getInterfaces();
		System.out.println(Arrays.toString(classes));
		
		System.out.println(class1.getSimpleName());
		System.out.println(class1.getTypeName());
		
	}
	
	//2使用反射获取类的构造方法,创建对象
	public static void reflectOpe2() throws Exception{
		//(1)获取类的类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取类的构造方法 Constructor
		Constructor<?>[] cons=class1.getConstructors();
		for (Constructor<?> con : cons) {
			System.out.println(con.toString());
		}
		//(3)获取类中无参构造
		Constructor<?> con=class1.getConstructor();
		Person zhangsan=(Person)con.newInstance();
		Person lisi=(Person)con.newInstance();
		System.out.println(zhangsan.toString());
		System.out.println(lisi.toString());
		//简便方法:类对象.newInstance();
		Person wangwu=(Person)class1.newInstance();
		System.out.println(wangwu.toString());
		//(4)获取类中带参构造方法
		Constructor<?> con2=class1.getConstructor(String.class,int.class);
		Person xiaoli=(Person)con2.newInstance("晓丽",20);
		System.out.println(xiaoli.toString());
		
	}
	
	//3使用反射获取类中的方法,并调用方法
	public static void reflectOpe3() throws Exception{
		//(1)获取类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取方法  Method对象
		//2.1getMethods() 获取公开的方法,包括从父类继承的方法
		//Method[] methods=class1.getMethods();
		//2.2getDeclaredMethods() 获取类中的所有方法,包括私有、默认、保护的 、不包含继承的方法
		Method[] methods=class1.getDeclaredMethods();
		for (Method method : methods) {
			System.out.println(method.toString());
		}
		//(3)获取单个方法
		//3.1eat
		Method eatMethod=class1.getMethod("eat");
		//调用方法
		//正常调用方法  Person zhangsan=new Person();  zhangsan.eat();
		Person zhangsan=(Person)class1.newInstance();
		eatMethod.invoke(zhangsan);//zhangsan.eat();
		System.out.println("------------------");
		//3.2toString
		Method toStringMethod=class1.getMethod("toString");
		Object result=toStringMethod.invoke(zhangsan);
		System.out.println(result);
		System.out.println("-------------------");
		//3.3带参的eat 
		Method eatMethod2=class1.getMethod("eat", String.class);
		eatMethod2.invoke(zhangsan, "鸡腿");
		
		//3.4获取私有方法
		Method privateMethod=class1.getDeclaredMethod("privateMethod");
		//设置访问权限无效
		privateMethod.setAccessible(true);
		privateMethod.invoke(zhangsan);
		
		//3.4获取静态方法
		Method staticMethod=class1.getMethod("staticMethod");
		//正常调用 Person.staticMethod
		staticMethod.invoke(null);
		
	}
	
	//4使用反射实现一个可以调用任何对象方法的通用方法
	public static Object invokeAny(Object obj,String methodName,Class<?>[] types,Object...args) throws Exception {
		//1获取类对象
		Class<?> class1=obj.getClass();
		//2获取方法
		Method method=class1.getMethod(methodName, types);
		//3调用
		return method.invoke(obj, args);
	}
	
	//5使用反射获取类中的属性
	public static void reflectOpe4() throws Exception{
		//(1)获取类对象
		Class<?> class1=Class.forName("com.qf.chap17_1.Person");
		//(2)获取属性(字段) 公开的字段,父类继承的字段
		//Field[] fields=class1.getFields(); 
		//getDeclaredFields()获取所有的属性,包括私有,默认 ,包含,
		Field[] fields=class1.getDeclaredFields();
		System.out.println(fields.length);
		for (Field field : fields) {
			System.out.println(field.toString());
		}
		//(3)获取name属性
		Field namefield=class1.getDeclaredField("name");
		namefield.setAccessible(true);
		//(4)赋值  正常调用  Person zhangsan=new Person(); zhangsan.name="张三";
		Person zhangsan=(Person)class1.newInstance();
		namefield.set(zhangsan, "张三"); //zhangsan.name="张三";
		//(5) 获取值
		System.out.println(namefield.get(zhangsan));// zhangsan.name
	}
}

18.5 设计模式


18.5.1 概念

  • 一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
  • 可以简单理解为特定问题的固定解决方法。
  • 在Gof的《设计模式》书中描述了23 种设计模式。

18.5.2 好处

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、重用性。

18.5.3 工厂设计模式

开发中有一个非常重要的原则“开闭原则”,对拓展开放、对修改关闭。

工厂模式主要负责对象创建的问题。

可通过反射进行工厂模式的设计,完成动态的对象创建。

案例演示:

Usb类:

/**
 * 父类产品
 * @author wgy
 *
 */
public interface Usb {
	void service();
}

Mouse类:

public class Mouse implements Usb{

	@Override
	public void service() {
		System.out.println("鼠标开始工作了.....");
	}

}

Fan类:

public class Fan implements Usb{

	@Override
	public void service() {
		System.out.println("风扇开始工作了...");
	}

}

KeyBoard类:

public class KeyBoard implements Usb{

	@Override
	public void service() {
		System.out.println("键盘开始工作了...");
	}

}

UsbFactory类:

public class UsbFactory {
	public static Usb createUsb(String type) {//类型的全名称 com.qf.
		Usb usb=null;
		Class<?> class1=null;
		try {
			class1 = Class.forName(type);
			usb=(Usb)class1.newInstance();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
		return usb;
	}
}

TestUsb测试类:

public class TestUsb {
	public static void main(String[] args) throws Exception{
		System.out.println("=========请选择 1 鼠标  2风扇 3 u盘===========");
		Scanner input=new Scanner(System.in);
		String choice=input.next();
		//1 = com.qf.chap17_2.Mouse
		//2 = com.qf.chap17_2.Fan
		//3 = com.qf.chap17_2.Upan
		//4 = com.qf.chap17_2.KeyBoard
		Properties properties=new Properties();
		FileInputStream fis=new FileInputStream("src\\usb.properties");
		properties.load(fis);
		fis.close();
		
		Usb usb=UsbFactory.createUsb(properties.getProperty(choice));
		if(usb!=null) {
			System.out.println("购买成功");
			usb.service();
		}else {
			System.out.println("购买失败,您要购买的产品不存在");
		}
	}
}

usb.properties配置文件。

1=com.qf.chap17_2.Mouse
2=com.qf.chap17_2.Fan
3=com.qf.chap17_2.Upan
4=com.qf.chap17_2.KeyBoard

18.5.4 单例模式

单例(Singleton):只允许创建一个该类的对象。

方式一:饿汉式(类加载时创建,天生线程安全)。

public class SingleTon {
	private static final SingleTon instance=new SingleTon();
	private SingleTon() {}
	public static SingleTon getInstance() {
		return instance;
	}
}

方式二:懒汉式(使用时创建,线程不安全,加同步)。

public class SingleTon2 {
	// 创建对象
	private static SingleTon2 instance = null;

	// 私有化构造方法
	private SingleTon2() {
	}

	// 静态方法
	public static  SingleTon2 getInstance() {
		if(instance==null) {//提高执行效率
			synchronized (SingleTon2.class) {
				if (instance == null) {
					instance = new SingleTon2();
				}
			}
		}
		return instance;
	}
}

方式三:懒汉式(静态内部类写法)

public class SingleTon3 {
	private SingleTon3() {}
	
	private static class Holder{
		static SingleTon3 instance=new SingleTon3();
	}
	
	public static SingleTon3 getInstance() {
		return Holder.instance;
	}
}

18.6 枚举


枚举是一个引用类型,枚举是一个规定了取值范围的数据类型。

  • 枚举变量不能使用其他的数据,只能使用枚举中常量赋值,提高程序安全性。

  • 定义枚举使用enum关键字。

  • 枚举的本质:

    • 枚举是一个终止类,并继承Enum抽象类。
    • 枚举中常量是当前类型的静态常量。

案例演示:

/**
 * 性别枚举
 */
public enum Gender {
	MALE,FEMALE;
}

注意:

  • 枚举中必须要包含枚举常量,也可以包含属性、方法、私有构造方法。
  • 枚举常量必须在前面,多个常量之间使用逗号隔开,最后分java号可写可不写。

18.7 注解


18.7.1 概念

注解(Annotation):是代码里的特殊标记, 程序可以读取注解,一般用于替代配置文件。

开发人员可以通过注解告诉类如何运行。

  • 在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。

18.7.2 定义注解

定义注解使用@interface关键字,注解中只能包含属性。

常见注解:@Override、@Deprecated

案例演示:

public @interface MyAnnotation {
	//属性(类似方法)
	String name() default "张三";
	int age() default 20;
	
}

18.7.3 注解属性类型

  • String类型

  • 基本数据类型

  • Class类型

  • 枚举类型

  • 注解类型

  • 以上类型的一维数组

18.7.4 元注解

元注解:用来描述注解的注解。

@Retention:用于指定注解可以保留的域。

  • RetentionPolicy.CLASS:
    注解记录在class文件中,运行Java程序时, JVM不会保留,此为默认值。

  • RetentionPolicy.RUNTIME:
    注解记录在 class文件中,运行Java程序时,JVM会保留,程序可以通过反射获取该注释

  • RetentionPolicy.SOURCE:
    编译时直接丢弃这种策略的注释。

@Target:

  • 指定注解用于修饰类的哪个成员。

案例演示:

PersonInfo注解类:

@Retention(value=RetentionPolicy.RUNTIME)
@Target(value= {ElementType.METHOD})
public @interface PersonInfo {
	String name();
	int age();
	String sex();
}

Person类:

public class Person {

	@MyAnnotation()
	public void show() {
		
	}
	
	//@MyAnnotation2(value="大肉",num=25)
	public void eat() {
		
	}
	
	@PersonInfo(name="小岳岳",age=30,sex="男")
	public void show(String name,int age,String sex) {
		System.out.println(name+"==="+age+"===="+sex);
	}
	
}

TestAnnotation类:

public class Demo {
	public static void main(String[] args) throws Exception{
		//(1)获取类对象
		Class<?> class1=Class.forName("com.qf.chap17_5.Person");
		//(2)获取方法
		Method method=class1.getMethod("show", String.class,int.class,String.class);
		//(3)获取方法上面的注解信息 personInfo=null
		PersonInfo personInfo=method.getAnnotation(PersonInfo.class);
		//(4)打印注解信息
		System.out.println(personInfo.name());
		System.out.println(personInfo.age());
		System.out.println(personInfo.sex());
		//(5)调用方法
		Person yueyue=(Person)class1.newInstance();
		method.invoke(yueyue, personInfo.name(),personInfo.age(),personInfo.sex());

	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/184199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

知名休闲服饰品牌——慕尚集团借力泛微实现统一办公、业务协同

客户简介 宁波中哲慕尚控股有限公司&#xff08;以下简称慕尚集团&#xff09;是中国知名的由新零售模式驱动的休闲时尚服饰多品牌运营公司。 旗下品牌有GXG,gxgjeans,gxg.kids,MODE COMMUTER等&#xff0c;覆盖时尚男女装、童装市场和其他时尚领域。2019年5月慕尚集团正式登…

不要在线上滥用CopyOnWriteArrayList,姿势不对性能真的很拉胯

从JDK1.5版本&#xff0c;JAVA提供了线程安全的List增强版CopyOnWriteArrayList&#xff0c;其保持线程安全的方式是&#xff1a;每次修改数据时&#xff0c;不会直接修改数据&#xff0c;而是把数据复制出来一份&#xff0c;对复制出来的数组进行操作。 通过这样的机制&#…

【图像算法】马赛克识别

【目的】 校验视频中出现马赛克的频率&#xff0c;抽象成将视频切割成图片&#xff0c;对每张代测图片进行自动化验证。 【实现】 图像边缘检测算法识别 算法步骤&#xff1a; 使用高斯滤波器&#xff0c;以平滑图像&#xff0c;滤除噪声。计算图像中每个像素点的梯度强度和…

buuctf-web-[BJDCTF2020]Easy MD51

打开环境一个简单的页面查看源代码一个get传参&#xff0c;随便输入试试看输入1,1",1,均无反应&#xff0c;每次遇到这种有输入框的都以为是sql注入&#xff0c;但是题目为md5标头里面看到提示select * from admin where passwordmd5($pass,true)搜索相关漏洞&#xff0c;…

gost 常用tunnel配置示例(隧道模式)

gost是用golang语言实现的一个安全隧道。地址位于&#xff1a;https://github.com/ginuerzh/gost是一个不可多得的隧道工具。至于什么是隧道&#xff1f; 就是可以通过这个工具传输一些其他协议的数据。就像这个样子。隧道有什么用呢&#xff1f;可以起到一些加速的作用或者流量…

Array.prototype.from()

Array.from() 用于将类数组对象或可迭代对象转化为一个新的浅拷贝数组实例。 let arr Array.from({length:3},(_,i)>({id:item-${i1}}))console.log(arr)Array.from()转换数组 // Array.from 转换成数组let arr2 Array.from(chixinAwen)console.log(arr2) 示例&#xff1a…

如何免安装使用 Python?推荐 17 个在线的 Python 解释器

安装 Python 很容易&#xff0c;但或许你正在用智能手机/平板电脑&#xff0c;在用不允许安装软件的电脑&#xff0c;或者因为其它原因无法安装 Python。那么&#xff0c;如何通过免安装的方式使用 Python 呢&#xff1f; 本文将介绍 17 个免费的 Python 解释器和交互式 Shell…

百里挑一,4款免费又实用的软件,用一次就爱上

好看的皮囊千篇一律&#xff0c;实用的软件百里挑一&#xff0c;下面几款软件都是笔者收集多年所得&#xff0c;实用且免费。 1、坚果云 这是一款颠覆许多人认知的网盘工具&#xff0c;免费使用无广告&#xff0c;不限速的优点就比某度网盘强百倍&#xff0c;支持任何设备&…

AOP案例:测量业务层接口万次执行时间

测量业务层接口万次执行时间1. 准备1.1 service层&#xff1a;1.2 dao层&#xff1a;1.3 SpringConfig配置类&#xff1a;2. AOP2.1 通知类2.2 测试类&#xff1a;3. 问题及改进1. 准备 需求&#xff1a;任意业务层接口执行均可显示执行的时长&#xff1b; 切入点配置&#x…

(day9) 自学Java——常用API

AIP就是Java已经写好的各种功能的java类 目录 1.Math 2.System 3.Runtime 4.Object 5.对象工具类Objects 6.BIgInteger 7.BigDecima 8.正则表达式 (1)爬虫 (2)带条件爬取&#xff0c;贪婪爬取和识别正则的两个方法 (3)捕获分组和非捕获分组 9.JDK7以前时间相关类 …

一起自学SLAM算法:12.3 autoware导航系统

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 上面介绍的ros-navigation和riskrrt导航系统主要都是用于机器人的低速导航&#xff0c;并且大多基于2D地图。而autoware导航系统主要用于无人驾驶汽车的高速导航&#xff0c;并且基于3D地图。除了所导航速度高一…

软件工程(一)——软件开发模型和方法

目录 &#xff08;一&#xff09;软件开发方法 &#xff08;二&#xff09;瀑布模型 &#xff08;三&#xff09;原型模型 &#xff08;四&#xff09;螺旋模型与增量模型 &#xff08;五&#xff09;V模型、喷泉模型、RAD模型 (六) 统一过程&#xff08;RUP&#xff09; …

idea 中 connot run program “svn“ 系统找不到文件

idea 中 connot run program “svn“ 系统找不到文件1. idea中svn的问题1.1 idea connot run program "svn"1.1.1 解决办法-重装svn1.2 idea中check out灰色不可用1.2.1 解决办法—装插件1. idea中svn的问题 1.1 idea connot run program “svn” 如图&#xff1a;…

2023年机床工具行业研究报告

第一章 行业概况 生产和销售机床工具的行业。机床是指制造机器的机器&#xff0c;亦称工作母机或工具机&#xff0c;习惯上简称机床。一般分为金属切削机床、锻压机床和木工机床等。现代机械制造中加工机械零件的方法很多&#xff1a;除切削加工外&#xff0c;还有铸造、锻造、…

【ES实战】索引生命周期管理(一)

索引生命周期管理IL&#xff2d;&#xff08;index lifecycle management&#xff09; 文章目录索引生命周期管理IL&#xff2d;&#xff08;index lifecycle management&#xff09;概述版本矩阵主要概念索引生命周期阶段的过渡阶段的执行生命周期中的操作生命周期策略索引翻滚…

AzureRT:一款能够实现各种Azure红队技战术的PowerShell模块

关于AzureRT AzureRT是一款能够实现各种Azure红队技战术的PowerShell模块&#xff0c;在AzureRT的帮助下&#xff0c;广大研究人员可以从攻击者的角度来与Azure和Azure AD进行交互&#xff0c;以此来测试目标环境的安全性。 AzureRT可以帮助广大研究人员测试和处理基于访问令…

【工具】操作PDF推荐的java依赖

Apache PDFBox |一个 Java PDF 库 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox-app</artifactId><version>2.0.27</version></dependency> Apache PDFBox - A Java PDF Library Apache PDFBox 库…

超详解线段树(浅显易懂)

一&#xff0c;什么是线段树&#xff1f;线段树是怎样的树形结构?线段树是一种二叉搜索树&#xff0c;而二叉搜索树&#xff0c;首先满足二叉树&#xff0c;即每个结点最多有两颗子树&#xff0c;并且是一颗搜索树&#xff0c;我们要知道&#xff0c;线段树的每个结点都存储了…

用于在过程工业中参数化配置现场设备的移动式解决方案

EndressHauser提供了一个组合套件&#xff08;包含Field Xpert和Softing的mobiLink通信工具&#xff09;&#xff0c;可用于参数化配置和现场调试。 &#xff08;将Softing的mobiLink通信工具与EndressHauser的Field Xpert SMT70或SMT77平板电脑相结合使用&#xff0c;可为用户…

再见 Matplotlib 和 Seaborn ,Python 画图建议用这个

本文主要介绍 Python 中用来替代 Matplotlib 和 Seaborn 的可视化工具 plotly&#xff0c;并结合实例讲解了 plotly 的优点和用法&#xff0c;满足了可视化绘图的交互需求。 数据可视化是人脑有效理解各种信息的最舒适、最直观的方式。对于需要处理数据的人来说&#xff0c;能…