黑马程序员_JavaSE基础知识总结十五:反射

JAVASE+AI(超详细版-黑马程序员 a. 对象是一种特殊的数据结构,可以用来记住一个事物的数据,从而代表该事物。b. 步骤:c. 对象的本质上是一种特殊的数据结构(可以理解成一张表)d.对象在计算机中是什么?可以让设备中的程序与网络上其他设备中的程序进行数据交互的技术(实现网络通信)。基本的通信架构有 2 种形式: CS 架构( Client 客户端 /Server 服务端 ) 、 BS 架构 (Browser 浏览器 /Server 服务端 )。无论是 CS 架构,还是 BS 架构的软件都必须依赖网络编程! 阅读详情

------ android培训java培训、期待与您交流! ----------



一、反射的基本概念

反射的概念是由Smith 1982 年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。Java 中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM 中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成

本很高。



二、Java中的类反射

Reflection Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,

或者说自审或“自省”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal或者C++ 中就没有办法在程序中获得函数定义相关的信息。

1、reflection的工作机制

程序运行时,java 系统会一直对所有对象进行所谓的运行时类型识别,这项信息记录了每个对象所属的类。通过专门的类可以访问这些信息。用来保存这些信息的类是class 类,class类为编写可动态操纵的java 代码程序提供了强大功能

构造Class 对象有种方式:

1、Class.forName();


<span style="font-size:18px;color:#333333;">try {
// 构造Class 对象的第一种方法
	Class clazz = Class.forName("java.lang.String");
	Object obj = clazz.newInstance();
	System.out.println(obj);
		} catch ( ClassNotFoundException e ) {
	e.printStackTrace();
		} catch (IllegalAccessException e) {
	e.printStackTrace();
		} catch ( InstantiationException e) {
	e.printStackTrace();
}</span>

2、.class

<span style="font-size:18px;color:#333333;">try {
// 构造Class 对象的第二种方法
	Class stringClass = String.class;
	System.out.println(stringClass);
		} catch ( ClassNotFoundException e ) {
	e.printStackTrace();
		} catch (IllegalAccessException e) {
	e.printStackTrace();
		} catch ( InstantiationException e) {
	e.printStackTrace();
}</span>

3、Object.getClass()

<span style="font-size:18px;color:#333333;">try {
// 构造Class 对象的第三种方法
	String s = "s";
	stringClass = s.getClass();
	System.out.println(stringClass);
		} catch ( ClassNotFoundException e ) {
	e.printStackTrace();
		} catch (IllegalAccessException e) {
	e.printStackTrace();
		} catch ( InstantiationException e) {
	e.printStackTrace();
}</span>

类对象的比较:

相同的类:

Class clazz = Class.forName("java.lang.String");

Class stringClass = String.class;

System.out.println("字符串类对象的比较=" +(clazz == stringClass));

不同的类:

Class stringClass = String.class;

Class intClass = int.class;

System.out.println("字符串类对象和Int 类对象的比较=" +(stringClass == intClass));

3、Java反射中的主要类和方法

软件包java.lang.reflect

提供类和接口,以获取关于类和对象的反射信息。

Constructor 构造函数对象

<span style="font-size:18px;color:#333333;">class A {
public A() {
}
public A( String s ) {
}
}
…
A a = new A();
Class aClass = a.getClass();
//得到类对象的所有公共的构造函数对象
Constructor[] constructors = aClass.getConstructors();
// 得到类对象特定的公共构造函数对象

Constructor c = aClass.getConstructor(String.class);
// 获取全部声明的构造方法

Constructor[] c1 = aClass.getDeclaredConstructors();
for ( Constructor c1 : constructors ) {
System.out.println( "构造方法的名称=" + c1.getName() );
System.out.println( " 构造方法的修饰符=" +
Modifier.toString(c1.getModifiers()) );
Class[] clazz1 = c1.getParameterTypes();
for ( Class cs : clazz1 ) {
	System.out.println("参数类型:"+cs.getName());
}
}</span>

②Method

<span style="font-size:18px;color:#333333;">Method[] ms = aClass.getDeclaredMethods();
for ( Method ms1 : ms ) {
System.out.println();
System.out.println( "方法的名称=" + ms1.getName() );
System.out.println( " 方法的修饰符=" + ms1.getModifiers() + ":" +
Modifier.toString(ms1.getModifiers()) );
System.out.println( " 方法的修饰符是否为public=" +
Modifier.isPublic(ms1.getModifiers()) );
Class[] clazz1 = ms1.getParameterTypes();
for ( Class cs : clazz1 ) {
System.out.println("参数类型:"+cs.getName());
}
System.out.println( "方法是否带有可变数量的参数=" + ms1.isVarArgs() );
System.out.println( "方法的返回类型:"+ms1.getReturnType().getName());
}</span>

③Field

<span style="font-size:18px;color:#333333;">Field[] f = aClass.getDeclaredFields();
B b = new B();
for ( Field f1 : f ) {
System.out.println();
System.out.println( "变量的名称=" + f1.getName() );
System.out.println( " 变量的修饰符=" +
Modifier.toString(f1.getModifiers()) );
System.out.println( "变量的类型=" + f1.getType().getName() );
System.out.println( "变量的值=" + f1.get(b) );
}</span>

④Class

<span style="font-size:18px;color:#333333;">Class[] classes = aClass.getInterfaces();
for ( Class c3 : classes ) {
System.out.println("接口名称:" + c3.getName());
}
// 获取类对象的父类
Class c4 = aClass.getSuperclass();
System.out.println("父类名称:" + c4);
// 获取类对象的包对象
String pName = String.class.getPackage().getName();
System.out.println("String 所在的包名称:" + pName);
System.out.println("aClass 是否为接口:" + aClass.isInterface());
System.out.println("C 是否为接口:" + C.class.isInterface());
System.out.println("类名:" + String.class.getName());
System.out.println("类名的简称:" + String.class.getSimpleName());</span>

3、开始使用Reflection

打印一个类声明所有内容

<span style="font-size:18px;color:#333333;">import java.lang.reflect.*;

class ClassRefTest1 {
	public static void main(String[] args) {
		try {
			Class c = Test.class;
			// 先判断类对象的类型
			String classType = "";
			if (c.isInterface()) {
				classType = "interface ";
			} else {
				classType = "class ";
			}
			int mod = c.getModifiers();
			Class[] iClass = c.getInterfaces();
			String classInterface = "";
			if (iClass != null && iClass.length != 0) {
				for (int i = 0; i < iClass.length; i++) {
					classInterface += iClass[i].getSimpleName();
					if (i != iClass.length - 1) {
						classInterface += ", ";
					}
				}
			}
			Class sClass = c.getSuperclass();
			String pName = c.getPackage() == null ? "" : c.getPackage()
					.getName();
			String classSuper = sClass.getSimpleName();
			if (pName != null && !"".equals(pName)) {
				System.out.println("package " + pName);
			}
			String classModifier = Modifier.toString(mod);
			if (!"".equals(classModifier)) {
				System.out.print(classModifier + " ");
			}
			System.out.print(classTypes + c.getSimpleName());
			if (sClass != null) {
				System.out.print(" extends " + classSuper);
			}
			if (!"".equals(classInterface)) {
				System.out.print(" implements " + classInterface);
			}
			System.out.println(" {");
			getConstr(c);
			getField(c);
			getMethod(c);
			System.out.println("}");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static void getConstr(Class c) throws Exception {
		Constructor[] constructors = c.getDeclaredConstructors();
		if (constructors != null && constructors.length != 0) {
			for (Constructor con : constructors) {
				int mod = con.getModifiers();
				String conModifier = Modifier.toString(mod);
				String conName = con.getName();
				Class[] clazzes = con.getParameterTypes();
				String conParams = "";
				if (clazzes != null && clazzes.length != 0) {
					for (int i = 0; i < clazzes.length; i++) {
						conParams += clazzes[i].getName();
						if (i != clazzes.length - 1) {
							conParams += ", ";
						}
					}
				}
				System.out.print(" ");
				if (conModifier != null && !"".equals(conModifier)) {
					System.out.print(conModifier + " ");
				}
				System.out.print(conName + "( ");
				if (!"".equals(conParams)) {
					System.out.print(conParams);
				}
				System.out.println(" ) {");
				System.out.println(" }");
			}
		}
	}

	private static void getField(Class c) throws Exception {
		// TODO 留为作业
	}

	private static void getMethod(Class c) throws Exception {
		// TODO 留为作业
	}
}

class A {
}

interface B {
}

class Test extends A implements B {
	public Test() {
	}

	public Test(String s) {
	}

	public String s;
	private int i;

	public static void test() {
	}

	public void test1() {
	}

	public void test1(String s) {
	}

	private void test2() {
	}
}</span>

构造对象

<span style="font-size:18px;color:#333333;">Class<Test> c = Test.class;
// 第一种构造对象的方法
//Test t = c.newInstance();//当类没有无参构造方法时,使用此方法构造对象失败
// 第二种构造对象的方法
Constructor<Test> con = c.getConstructor(String.class);
Test t = con.newInstance("abc");
System.out.println("Test 对象的S 属性值:"+t.s);
…
class Test extends A implements B {
//public Test() {
//
//}
public Test(String s) {
this.s = s;
}
public String s = "s";
private int i = 10;</span>

③方法

// 对象方法的普通调用

t.test1("abc");

// 对象方法的反射调用

Method m = c.getMethod("test3");

m.invoke(null);//调用静态方法

④变量

<span style="font-size:18px;color:#333333;">Field f = c.getDeclaredField("i");
System.out.println("f="+f);
//System.out.println("t.i="+f.get(t));
System.out.println("是否支持Java 语言访问检查:"+!f.isAccessible());
f.setAccessible(true);
System.out.println("t.i before="+f.get(t));
f.set(t, 20);
System.out.println("t.i after="+f.get(t));</span>



三、安全性和反射

在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,我们可能希望框架能够全面介入代码,无需考虑常规的介入限制。但是,在其它情况下,不受控制的介入会带来严重的安全性风险,例如当代码在不值得信任的代码共享的环境中运行时。

 

四、反射的两个缺点

反射是一种强大的工具,但也存在一些不足。

性能问题。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。

使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相应的直接代码更复杂。解决这些问题的最佳方案是保守地使用反射——仅在它可以真正增加灵活性的地方——记录其在目标类中的使用。











JavaSE——单元测试、反射、注解、动态代理 文章目录单元测试单元测试概述单元测试快速入门单元测试常用注解反射反射概述反射获取类对象反射获取构造器对象反射获取成员变量对象反射获取方法对象反射的作用-绕过编译阶段为集合添加数据反射的作用-通用框架的底层原理注解注解概述自定义注解元注解注解解析案例:注解解析的案例注解的应用场景一:Junit框架动态代理 单元测试 单元测试概述 单元测试 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法,因此,单元测试就是针对Java方法的测试,进而检查方法的正确性。 目前测试方法是怎么进行 阅读详情

相关推荐

黑马程序员JavaSE基础加强d6

———javaSE基础加强d6—01-Java高级技术-Junit单元测试———————————————————javaSE基础加强d6—02-Java高级技术-反射概述—————————————————————javaSE基础加强d6—04-Java高级技术-反射的作用————————————————————javaSE基础加强d6—06-Java高级技术-注解的解析————————————————————javaSE基础加强d6—07-Java高级技术-注解的应用场景——————————————

XingchenLielong的博客 909

二十二、反射黑马JavaSE笔记】

本文是博主自学b站黑马Java教程总结的笔记,本节对Java中的反射做了介绍

BoBooY的Java学习笔记 740

黑马程序员张孝祥JavaSE基础加强

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33749131的博客 3185

黑马程序员javaSE反射和新特性

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-1、类的加载概述和加载时机2、类加载器的概述和分类3、反射概述获取字节码文件对象的方式 Class类中的静态方法: static Class<?> forName(String className) -- 全路径类名 数据类型的静态属性 例如:

qq_33244063的博客 369

JavaSE学习】04-4Java高级(单元测试、反射、注解、动态代理、XML)

JavaSE(B站黑马)学习笔记 04-4Java高级(单元测试、反射、注解、动态代理、XML)

weixin_48074431的博客 454

黑马程序员JavaSE下部目录

P13 集合进阶-12-TreeMap练习3-利用TreeMap进行统计 14:21。P132 IO流-57-综合练习15-properties的基本使用 17:10。P121 IO流-48-综合练习04-网络爬虫(数据处理并写出) 15:58。P42 Stream流-08-综合练习3-自定义对象过滤并收集 11:49。P22 集合进阶-21-综合练习1-随机点名器的两种实现方式 07:15。P25 集合进阶-24-综合练习4~5-带权重的随机点名项目 08:49。

gengsj 708

JavaSE专栏介绍

网站地址:https://zsh-cs.github.io/ComputerNotes/JavaSE/index.html项目地址:https://github.com/Zsh-cs/ComputerNotes。欢迎访问我撰写的JavaSE笔记!

2401_83600210的博客 105

黑马程序员_JavaSE的网络编程和反射

1.网络编程 (1)每台机子有一个IP,找到对方的IP,然后本机某端口的进程发送数据过去。对方有着相应端口号的进程获取数据。 IP地址:网络中设备的标识。本地回环地址:127.0.0.1主机名:localhost 端口:标识进程的逻辑地址。 有效端口:0~65535,其中0~1024是系统使用或保留的端口。 (2)数据在网络上传输的常见协议: UDP: 1,将数据,源和目的封装在数据包

pengli228的专栏 364

黑马程序员——javaSE_反射

------- android培训、java培训、期待与您交流! ---------- 反射 1.反射就是把java类中的各种成分映射成相应的java类 2.java程序中的各个java类属于同一类事物,描述这类事物的类名就是Class 3.获取各个字节码对应的实力对象有三种方法 方法一:类名.class 方法二:对象.getclass(); 方法三:Class.

jinguodong1994的博客 413

JAVASE+AI实战指南:从基础到高阶开发全解析(黑马程序员深度版)

本文由黑马程序员资深学员分享,详细解析如何将AI工具深度融入JavaSE学习与开发全流程。从环境搭建、核心语法速通,到异常处理、IO流、多线程等进阶难题,再到网络编程、反射等高级特性,AI作为强大的“加速器”,能显著降低学习门槛、提升开发效率,帮助开发者专注于问题建模与架构设计,培养人机协同的高效开发思维。

weixin_29310631的博客 101

黑马程序员----JAVASE高级部分之反射

反射与反省

woaibeijixiong的专栏 812

黑马程序员——Java反射

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 自学Java第十三天笔记。本人是根据毕向东老师的JavaSE视频学习的。 Java反射 一.理解。 1.概述: 应用程序已经写好,后期出现的接口子类无法直接在该应用程序中用new创建对象。 既然子类不确定,可以通过对外提供配置文件的形式,将不确定的信息存储到配

zhaofengshiwo的专栏 450

Javase 高级技术 —— 01 反射

本文介绍了JavaSE中的单元测试和反射技术。单元测试部分讲解了Junit框架的优势,包括自动化测试和生成测试报告。反射部分详细说明了如何通过三种方式获取Class对象(类名.classClass.forName、对象.getClass()),并演示了如何获取和操作类的构造器、成员变量和方法。文中通过Dog类实例展示了反射的具体应用,包括暴力反射访问私有成员、调用方法等操作。这些技术为Java开发提供了更灵活的编程方式,特别适合框架开发和动态调用场景。

Celeste的博客 354

我的JAVASE 笔记(黑马ai加强篇)

1. 在开发中异常的常见处理方式是:底层的异常抛出去给最外层,最外层集中捕获处理。2. 底层的异常抛出去给最外层,最外层修复后重新运行。// 目标:掌握异常的处理方案1:底层异常都抛出去给最外层调用者,// 最外层捕获异常,记录异常,响应合适信息给用户。System.out.println("==程序开始...==");System.out.println("这次操作成功了~");System.out.println("这次操作失败了~");

gwq2098321904的博客 547

黑马程序员——JavaSE之对单例枚举和反射的看法一

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

buer的博客 789

JavaWeb笔记: 第01章_JavaSE回顾——Junit单元测试&反射&注解

这里写目录标题1. JavaWeb课程介绍一、为什么要学习JavaWeb?二、适用人群三、课程安排四、后期学习路径2. Java SE 内容补充2.1 Junit单元测试测试分类∶Junit使用∶在main方法里的测试Junit单元测试(白盒测试)2.2 反射获取class对象的方式class对象功能∶获取成员变量获取构造方法获取成员方法 & 获取类名反射案例2.3 注解 1. JavaWeb课程介绍 一、为什么要学习JavaWeb? 学习目的: 获得现在主流开发技术 Javaweb是什么

IAMLSL的博客 508

黑马java-JavaSE进阶-java高级技术

本文主要讲解了单元测试、单元测试框架、注解及动态代理部分内容。

qq_52649952的博客 1842

javase知识点总结

小编历时两个月学完了javase,下面是小编的一样学习经验分享,相信看了这篇博客对你会所有帮助!首先说说小编学习的视频来源,小编一直持有一颗白嫖的心理,所有学习的视频来源当然是白嫖的 视频来源:动力节点 在最新开始学习的时候,小编看的黑马视频,但是发现黑的视频较快,所有换了速度慢一点的动力节点,个人比较推荐的是老杜的视频讲解 接下来聊一聊重点的知识点 首先是基础知识,类的定义,基本数据类型,循环结构,终止循环结构的关键字,运算符,标识符学完这些你需要知道基本数据有那些怎么定义怎么使用,循环结构如何使

qq_53909398的博客 2455
上一篇: 黑马程序员_JavaSE基础知识总结十四:多线程
下一篇: 黑马程序员_JavaSE基础知识总结十六:流与文件
liulin90
博客等级 码龄11年 3粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值