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的更多相关文章

  1. Java反射应用--2

    Java反射开窍第一篇 明天再写

  2. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  3. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  4. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

  5. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  6. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  7. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  8. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  9. java反射 之 反射基础

    一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...

随机推荐

  1. vue element 表单验证不通过,滚动到固对应位置

    我们在使用elementIUI实现表单验证,内容比较多的时候,提示内容会被遮挡,这时候用户不清楚什么情况,还会连续点击提交按钮.这个时候需求来啦:我们需要在表单验证不通过的时候,页面滚动到对应的位置. ...

  2. 瞄到BindingGroup用法

    文章转载于https://www.cnblogs.com/dangnianxiaoqingxin/p/12653988.html 2.BindingGroup的使用 public class MyCl ...

  3. 深入浅出Dotnet Core的项目结构变化

    有时候,越是基础的东西,越是有人不明白.   前几天Review一个项目的代码,发现非常基础的内容,也会有人理解出错. 今天,就着这个点,写一下Dotnet Core的主要类型的项目结构,以及之间的转 ...

  4. 3610:20140827:161308.483 No active checks on server: host [192.168.1.10] not found

    3610:20140827:161308.483 No active checks on server: host [192.168.1.10] not found

  5. kubernets与API服务器进行交互

    一  为何需要与kubernets集群的API服务器进行交互 1.1  kubernets提供了一种downapi的资源可以将pod的元数据渲染成环境变量或者downward卷的形式挂载到容器的文件系 ...

  6. LeetCode1022. 从根到叶的二进制数之和

    题目 class Solution { public: int ans = 0; int sumRootToLeaf(TreeNode* root) { dfs(root,0); return ans ...

  7. 使用 TensorBoard 可视化模型、数据和训练

    使用 TensorBoard 可视化模型.数据和训练 在 60 Minutes Blitz 中,我们展示了如何加载数据,并把数据送到我们继承 nn.Module 类的模型,在训练数据上训练模型,并在测 ...

  8. Eclipse中的可视化图形界面设计插件windowbuilder

    对于eclipse平台上的可视化开发工具插件,有windowbuilder.visual editor等,今天就对windowbuilder说明: WindowBuilder功能特性等介绍,参考如下网 ...

  9. MongoDB查询优化--explain,慢日志

    引入 与Mysql数据库一样,MongoDB也有自己的查询优化工具,explain和慢日志 explain shell命令格式 db.collection.explain().<method(. ...

  10. 记录一下 ThreadLocal 与 WeakReference

    ThreadLocal & WeakReference Thread整体的模块图 Thread -> ThreadLocalMap 对于继承了 WeakReference Entry本身 ...