Java反射开窍--1
1.通过案例引出反射并体会反射的好处
案例:美团外卖 --->付款 ---》要么用微信支付 要么用支付宝支付
package com.zhaoss.test01;
//接口的制定方:美团外卖
public interface Mtwm {
//在线支付功能:
void payOnline();
}
public class WeChat implements Mtwm {
@Override
public void payOnline() {
//具体实现微信支付的功能:
System.out.println("我已经点了外卖,正在使用微信支付");
}
}
public class AliPay implements Mtwm {
@Override
public void payOnline() {
//具体实现微信支付的功能:
System.out.println("我已经点了外卖,正在使用支付宝进行支付");
}
}
public class BankCard implements Mtwm {
@Override
public void payOnline() {
//具体实现微信支付的功能:
System.out.println("我已经点了外卖,正在使用招商银行信用卡支付");
}
}
测试类:
public class Test {
public static void main(String[] args) {
//定义一个字符串,用来模拟前台的支付方式:
String str = "微信";
//str.equals("微信")---避免空指针异常,编程习惯要好,常量在左边
if ("微信".equals(str)) {
// 微信支付:
pay(new WeChat());
}
if ("支付宝".equals(str)) {
//支付宝支付:
pay(new AliPay());
}
if ("招商银行".equals(str)) {
pay(new BankCard());
}
}
//微信支付
public static void pay(WeChat wc) {
wc.payOnline();
}
//支付宝支付
public static void pay(AliPay ap) {
ap.payOnline();
}
//招商银行支付
public static void pay(BankCard bc) {
bc.payOnline();
}
}
看了上面的代码,大家肯定会觉得冗余哈,大家都学过面向对象的多态特性,可以将测试类中的方法进行简化,pay方法定义形参为Mtwm(美团外卖)这个接口,等我们调用时传入对应的实现类即可。于是,代码可以简化为如下:
public class Test {
public static void main(String[] args) {
//定义一个字符串,用来模拟前台的支付方式:
String str = "微信";
if ("微信".equals(str)) {
// 微信支付:
pay(new WeChat());
}
if ("支付宝".equals(str)) {
//支付宝支付:
pay(new AliPay());
}
if ("招商银行".equals(str)) {
pay(new BankCard());
}
}
//支付
public static void pay(Mtwm m) {
m.payOnline();
}
}
多态确实可以提高代码的扩展性,但是:扩展性没有达到最好。
怎么没有达到最好呐:上面的分支判断,还是需要手动的删除或者添加,当接入中国银行/广州银行/花旗银行等的时候,是需要修改这个测试代码类的。
那更好的解决办法:反射机制 利用反射实现上述功能:
public class Test {
public static void main(String[] args) {
//定义一个字符串,用来模拟前台的支付方式:
String str = "com.zhaoss.test01.AliPay"; //字符串:实际上:就是微信类的全限定路径
//下面的代码就是利用反射:
Class cls = Class.forName(str);
/*
代码解读,首先根据str所代表的AliPay的全限定类名,去得到AliPay的字节码对象cls(万物皆对象,这里理解为对象更好懂,接下来还会讲解Class这个类)
根据cls字节码对象去获取AliPay这个类的对象实例o,并根据cls获取字节码对象中的方法并执行
*/
Object o = cls.newInstance();
Method method = cls.getMethod("payOnline");
method.invoke(o);
}
//支付
public static void pay(Mtwm m) {
m.payOnline();
}
这样修改之后,程序变得更加的简洁,并且以后外部又有谁要实现这个接口,这个程序都不必再进行改动,实现了解耦。
2.通过概念再体会反射
反射概念:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象, 都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
帮助理解:
在编译后产生字节码文件的时候,类加载器子系统通过二进制字节流,负责从文件系统加载class文件。 在执行程序(java.exe)时候,将字节码文件读入JVM中--->这个过程叫做类的加载。然后在内存中对应创建一个java.lang.Class对象-->这个对象会被放入字节码信息中,这个Class对象,就对应加载那个字节码信息,这个对象将被作为程序访问方法区中的这个类的各种数据的外部接口。 所以:我们可以通过这个对象看到类的结构,这个对象就好像是一面镜子,透过镜子看到类的各种信息,我们形象的称之为反射 这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
疑惑点,需要解决:每个类被加载的时候,都只加载一次,创建该类对应的Class对象,这个对象会被放进字节码信息中,即每个类都有对应的字节码信息,而每个字节码信息中又存放了该类的Class对象,这个对象是反射得以实现的基础和关键。通过这个对象,获取到该类字节码中的各种信息,构造方法/属性/方法等。其它类加载时都会有一个Class对象创建,那java.lang.Class这个类本身加载的时候,是不是也创建一个自己的Class对象嘞?主要就是加粗这点有疑问,前面说的帮助理解。
补充:
动态语言vs静态语言
1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以 被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运 行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、 C++。
所以Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动 态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。 Java的动态性让编程的时候更加灵活!
3.Class类的理解--万物皆对象
通过Class类,可以得到具体的Class类的对象,字节码信息对象。得到这个后就可以获取剩下的属性方法构造方法等,既而创建该类的对象。

4.获取字节码信息的4种形式
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//案例:以Person的字节码信息为案例 /
//方式1:通过getClass() 方法获取
Person p = new Person();
Class c1 = p.getClass();
System.out.println(c1);
//方式2:通过内置class属性:
Class c2 = Person.class;
System.out.println(c2);
System.out.println(c1 == c2);
//注意:方式1和方式2 不常用 /
//方式3:--》用的最多:调用Class类提供的静态方法forName
Class c3 = Class.forName("com.zhaoss.test02.Person");
//方式4:利用类的加载器(了解技能点)
ClassLoader loader = Test.class.getClassLoader();
Class c4 = loader.loadClass("com.zhaoss.test02.Person");
}
}
5.可以作为Class这个类的类实例的种类
Class类的具体的实例:
(1)类:外部类,内部类
(2)接口
(3)注解
(4)数组
(5)基本数据类型
(6)void
/**
* @author wangcc
* @create 2020-11-04 1:30
**/
public class Demo {
public static void main(String[] args) {
Class c1 = Person.class;
Class c2 = Comparable.class;
Class c3 = Override.class;
int[] arr1 = {1, 2, 3};
Class c4 = arr1.getClass();
int[] arr2 = {5, 6, 7};
Class c5 = arr2.getClass();
System.out.println(c4 == c5);//结果:true .同一个维度,同一个元素类型,得到的字节码就是同一个
Class c6 = int.class;
Class c7 = void.class;
}
}
学习了这篇文章基本上就差不多了,接下来一篇就是反射的api调用,根据反射获取属性,方法,构造方法,各种修饰符的,创建对象,为属性赋值等操作。明天再写,太晚了今天。
Java反射开窍--1的更多相关文章
- Java反射应用--2
Java反射开窍第一篇 明天再写
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java反射(基础了解)
package cn.itcast_01; /** *Person类 */ public class Person { /** 姓名 */ private String name; ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- java反射学习之二万能EXCEL导出
一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
随机推荐
- Win Docker 安装C盘清理方法之一
背景 由于Docker默认安装到C盘,C盘空间越发的小了,虽然(win10)C盘满了并不会很大影响,但是强迫症患者是不能忍得 解决办法 查询https://stackoverflow.com/ques ...
- Spring--AOP、通知的执行顺序
AOP执行顺序 如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢? 可以通过指定order,order越小越是最先执行. 配置AOP执行顺序的三种方式: 通过实现Ordered接口 ...
- Java 双端队列接口 Deque
Deque 是一种支持在两端进行操作的线性结构,包含了栈和队列的功能.Java 中建议使用 Dqueue 的实现来替代遗留的 Stack 类.本文将介绍 Deque 提供的主要 API. 双端操作 A ...
- springboot异常处理之404
ps: 推荐一下本人的通用后台管理项目crowd-admin 以及newbee-mall增强版,喜欢的话给个star就好 源码分析 在springboot中默认有一个异常处理器接口ErrorConto ...
- 最新最简洁Spring Cloud Oauth2.0 Jwt 的Security方式
因为Spring Cloud 2020.0.0和Spring Boot2.4.1版本升级比较大,所以把我接入过程中的一些需要注意的地方告诉大家 我使用的版本是Spring boot 2.4.1+Spr ...
- python无法连接mysql,有个小坑,需要注意一下!
尝试用python链接mysql数据库,按照教程里链接了小半夜,就是没有链接上,找了各种文章,最后发现是版本的问题,我想使用的模块是MySQLdb,刚刚去他们的官网看了一下,最近一次更新是2014年, ...
- oracle字符集与乱码(转)
作者:hcling97 http://blog.sina.com.cn/hcling97 2013年5月15日 转载请注明出处 字符集问题一直叫人头疼,究其原因还是不能完全明白其运作原理. 在整 ...
- spring mvc + mybaties + mysql 完美整合cxf 实现webservice接口 (服务端、客户端)
spring-3.1.2.cxf-3.1.3.mybaties.mysql 整合实现webservice需要的完整jar文件 地址:http://download.csdn.net/detail/xu ...
- Java程序入门
编写Java源程序 在d:\day01 目录下新建文本文件,完整的文件名修改为HelloWorld.java ,其中文件名为HelloWorld ,后缀名必须为.java . 用记事本打开 在文件中键 ...
- 30分钟带你理解 Raft 算法
为什么需要 Raft? Raft 是什么? Raft 的目标 前置条件:复制状态机 Raft 基础 Leader 选举(选举安全特性) 日志复制(Leader只附加.日志匹配) 安全 学习资料 使用 ...