23种设计模式+额外常用设计模式汇总 (持续更新)
Java是一门准动态语言,是因为存在反射机制,如果你不会是不是就等于白学了?
看完不会,请评论,我亲自给你解释,嘻嘻!

什么是动态语言?

动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化。比如JavaScript便是一个典型的动态语言。
  
除此之外如Ruby、Python、OC等也都属于动态语言,而C、C++、Java等语言则不属于动态语言。

动态类型语言,就是类型的检查是在运行时做的,是不是合法的要到运行时才判断,例如JavaScript就没有编译错误,只有运行错误。

静态语言
  而静态类型语言的类型判断是在运行前判断(如编译阶段),比如java就是静态类型语言,静态类型语言为了达到多态会采取一些类型鉴别手段,如继承、接口,而动态类型语言却不需要,

Java的反射机制被视为Java为准动态语言的主要的一个关键性质,这个机制允许程序在运行时透过反射取得任何一个已知名称的class的内部信息,包括:

正在运行中的类的属性信息,正在运行中的类的方法信息,正在运行中的类的构造信息,正在运行中的类的访问修饰符,注解等等。

动态语言无时不刻在体现动态性,而静态语言也在通过其他方法来趋近于去弥补静态语言的缺陷。

为什么么要使用反射:

  1. 反射是框架设计的灵魂
    框架: 半成品软件。可以在框架的基础上进行软件开发,简化编码。学习框架并不需要了解反射,但是要是想自己写一个框架,那么就要对反射机制有很深入的了解。
  2. 解耦,提高程序的可扩展性
  3. 在运行时判断任意一个对象所属的类。
  4. 在运行时构造任意一个类的对象。
  5. 在运行时判断任意一个类所具有的成员变量和方法。
  6. 在运行时调用任意一个对象的方法。

什么是反射:

定义:

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

简单来说: 将类的各个组成部分封装成其他对象

反射机制的实现原理

Java代码在计算机中经历的三个阶段

  1. Source源代码阶段:.java被编译成.class字节码文件。
  2. Class类对象阶段:*.class字节码文件被类加载器加载进内存,并将其封装成Class对象(用于在内存中描述字节码文件),Class对象将原字节码文件中的成员变量抽取出来封装成数组Field[],将原字节码文件中的构造函数抽取出来封装成数组Construction[],在将成员方法封装成Method[]。当然Class类内不止这三个,还封装了很多,我们常用的就这三个。
  3. RunTime运行时阶段:创建对象的过程new。
获取Class对象的方式:
  1. Class.forname(“类全名”):
    将字节码加载进内存,返回Class对象。
    一般用于: 配置文件,将类名定义在配置文件中,读取文件,加载类。
  2. 类名.class:
    通过类名的属性Class获取
    一般用于: 参数传递
  3. 对象.getclass()获取:
    getclass()方法在Object类中定义
    一般用于: 对象获取字节码的方式

补充:
同一个字节码文件(*.class)在一次程序运行中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

举例:

public void Main() throws ClassNotFoundException {//方式一:Class.forName("全类名");Class cls1  = Class.forName("Test.Test");  //Person自定义实体类System.out.println("cls1 = " + cls1);//方式二:类名.classClass cls2 = Test.class;System.out.println("cls2 = " + cls2);//方式三:对象.getClass();Test tst= new Test();        Class cls3 =tst.getClass();System.out.println("cls3 = " + cls3);// == 比较三个对象System.out.println("cls1 == cls2 : " + (cls1 == cls2));    //trueSystem.out.println("cls1 == cls3 : " + (cls1 == cls3));    //true//结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。
}

Class对象功能:
获取功能:

1 获取成员变量们

Field[] getFields() :获取所有public修饰的成员变量
Field getField(String name)   获取指定名称的 public修饰的成员变量Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name)
//需要忽略访问权限修饰符的安全检查 setAccessible(true):暴力反射,不然会报错

具体测试看下文!

2.获取构造方法们

Constructor<?>[] getConstructors()
Constructor<T> getConstructor(类<?>... parameterTypes)  Constructor<?>[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

具体测试看下文!

3.获取成员方法们:

Method[] getMethods()
Method getMethod(String name, 类<?>... parameterTypes)  Method[] getDeclaredMethods()
Method getDeclaredMethod(String name, 类<?>... parameterTypes)
//需要忽略访问权限修饰符的安全检查 setAccessible(true):暴力反射,不然会报错

具体测试看下文!

4.获取全类名

String getName()

getClass()方法是Object类的方法,需要注意一点获取的类名是全类名(带有路径)
举例:

package Test;
public class Reflect {public static void main(String[] args) throws Exception {Class Tst = Test.class;String s=Tst.getName(); System.out.println(s);}
}

运行结果:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200503024319516.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzYyNzExOA==,size_16,color_FFFFFF,t_70)
Field:成员变量
  1. 设置值 void set(Object obj, Object value)
  2. 获取值 get(Object obj)

举例:

package Test;
public class Test {public String a;protected String b;private String c;String d;
}package Test;import java.lang.reflect.Field;public class Reflect {public static void main(String[] args) throws  Exception {Class Tst = Test.class;Test tst=new Test();System.out.println("-------------------测试getField--------------------");Field[] fields=Tst.getFields(); for(Field f:fields){System.out.println(f);}Field a=Tst.getField("a");a.set(tst, "我是设置值");System.out.println(a.get(tst));System.out.println("\n-------------测试getDeclaredField------------------");Field[] fields2=Tst.getDeclaredFields();for(Field f:fields2){f.setAccessible(true);//不加出不来,详情请看上文System.out.println(f);}Field b=Tst.getDeclaredField("b");b.set(tst, "我是私有的设置值");System.out.println(b.get(tst));}
}

测试结果:

Constructor:构造方法

创建对象:T newInstance(Object… initargs)
注意:如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法
作用就是用它来创建对象
举例:

package Test;public class Test {public String a;//构造方法public Test( ) {}public Test(String a) {this.a = a;}}package Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;public class Reflect {public static void main(String[] args) throws Exception {Class Tst = Test.class;Constructor[] constructors = Tst.getConstructors();for (Constructor constructor : constructors) { // Constructor 对象reflect包下的 import java.lang.reflect.Constructor;System.out.println(constructor);}System.out.println("------------------无参构造函数创建对象----------------------");Constructor cst=Tst.getConstructor(); //获得无参构造函数System.out.println(cst);Object test=cst.newInstance(); //利用无参构造函数创建对象System.out.println(test);System.out.println("------------------有参构造函数创建对象----------------------");Constructor cst2=Tst.getConstructor(String.class); //获得有参构造函数System.out.println(cst2);Object test2=cst2.newInstance("张3");//利用有参构造函数创建对象System.out.println(test2);System.out.println("------------------基于Class创建对象----------------------");Object test3=Tst.newInstance();//只能用于无参构函数,而且已经被弃用,不建议使用System.out.println(test3);}
}


喜欢问问题的小朋友要来了?
为什么没有getDeclaredConstructor方法和getDeclaredConstructors方法?
为什么?为什么?
有啊!!
getDeclaredConstructor方法可以获取到任何访问权限的构造器,而getConstructor方法只能获取public修饰的构造器。具体不再测试。此外在构造器的对象内也有setAccessible(true);方法,并设置成true就可以操作了。
关于为什么要使用private访问权限的构造器,使用这个构造器不就不能外部访问了嘛,不也就无法进行实例化对象了吗?无法在类的外部实例化对象正是私有构造器的意义所在,在单例模式下经常使用,整个项目只有一个对象,外部无法实例化对象,可以在类内的进行实例化并通过静态方法返回,由于实例化的对象是静态的,故只有一个对象,也就是单例的,这就是单例模式中的饿汉模式,不管是否调用,都创建一个对象。

Method:方法对象

执行方法:Object invoke(Object obj, Object… args)
获取方法名称:String getName();

举例:

package Test;public class Test {public String a;// 构造方法public Test() {}public Test(String a) {this.a = a;}public void do_Something()    {System.out.println("吃饭睡觉打豆豆");}public String do_Something(String s)  {System.out.println("吃饭睡觉打"+s);return "爽";}
}package Test;import java.lang.reflect.Method;public class Reflect {public static void main(String[] args) throws Exception {Class Tst = Test.class;Method[] mtd=Tst.getMethods();for(Method m:mtd) System.out.println(m);}
}

运行结果:

举例2.0:

package Test;public class Test {public String a;// 构造方法public Test() {}public Test(String a) {this.a = a;}public void do_Something()    {System.out.println("吃饭睡觉打豆豆");}public String do_Something(String s)  {System.out.println("吃饭睡觉打"+s);return "爽";}
}
package Test;import java.lang.reflect.Method;public class Reflect {public static void main(String[] args) throws Exception {Class Tst = Test.class;Test test = new Test();System.out.println("-----------------无参测试----------------------");Method mtd1 = Tst.getMethod("do_Something");// 获得无参的方法Object return_Value = mtd1.invoke(test); // 调用方法// 有返回值就得到一个值,没有就得到一个nullSystem.out.println(return_Value);System.out.println("-----------------含参测试----------------------");Method mtd2 = Tst.getMethod("do_Something", String.class);// 获得无参的方法Object return_Value2 = mtd2.invoke(test, "张三"); // 调用方法// 有返回值就得到一个值,没有就得到一个nullSystem.out.println(return_Value2);}
}

运行结果:

总结

这时候又会有小朋友问:
为什么要这么麻烦,我直接调用不就好了?

不知你是否发现,从类的创建的方法的使用,所有的一切都是用的字符串,那么也就是说,我可以通过读入数据,或者配置文件的方式,创建类,调用方法。

举个简单点的例子:
就拿英雄联盟这款游戏来说,这游戏三天两头的轮换一个娱乐模式,难道每次上线都要对源代码进行修改,今天在Client调用“无限活力”,明天就要调用"魄罗大乱斗”,每天就对着源码改?几万行的代码就这么放心让你改?除非你老板想做空公司,故意的!必然不可能,这时候我们就算哪一个txt文件,就放一行字符串,用反射之后,只用改txt文件不就完了!不用反射,是做不到用字符串创建类,和运行方法(别抬杠,写个if-else 或者 switch啥的)。

举例可能不太恰当,一般不会使用txt,一般使用XML或者java配置文件。

写在最后:
我叫风骨散人,名字的意思是我多想可以不低头的自由生活,可现实却不是这样。家境贫寒,总得向这个世界低头,所以我一直在奋斗,想改变我的命运给亲人好的生活,希望同样被生活绑架的你可以通过自己的努力改变现状,深知成年人的世界里没有容易二字。目前是一名在校大学生,预计考研,热爱编程,热爱技术,喜欢分享,知识无界,希望我的分享可以帮到你!
如果有什么想看的,可以私信我,如果在能力范围内,我会发布相应的博文!
感谢大家的阅读!

『设计模式』反射,反射程序员的快乐!为什么我老是加班?为什么我工资不如他多?原来是我不懂反射!相关推荐

  1. Unity C#基础之 反射反射,程序员的快乐

    反射反射,程序员的快乐 这句话想必大家都经常听过,基本上在绝大多数的框架和一些设计模式中都能看到反射的身影(MVC.IOC.AOP.O/RM), 反射:是.Net Framework提供的一个帮助类库 ...

  2. 大话设计模式(九 反射——程序员的快乐!)

    (续上篇)          "到底如何去改良策略模式呢?"小菜恳切地问道.          "你仔细观察过没有,你的代码,不管是用工厂模式写的,还是用策略模式写的,那 ...

  3. 程序员的快乐就是这么朴素无华且枯燥

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:github.com/ZhongFuChen- 我是一个程序员,外行人都以为我是修电脑的,我笑了笑,随意ctrl c+ctrl ...

  4. 要嫁就嫁程序员!原因很简单:五成表示工资愿交给另一半!

    俗话说得好,嫁人就嫁程序员,钱多话少脾气好.虽然看上去程序员应该不愁婚嫁,但近日也出现了年薪百万程序员遭亲妈一元起"拍卖"相亲的新闻.程序员的恋爱生活到底怎么样?BOSS直聘就程序 ...

  5. 测试/开发程序员喜欢跳槽?跳了就能涨工资吗?

    目录:导读 前言 一.Python编程入门到精通 二.接口自动化项目实战 三.Web自动化项目实战 四.App自动化项目实战 五.一线大厂简历 六.测试开发DevOps体系 七.常用自动化测试工具 八 ...

  6. html5编写微信留言,HTML5春节(支持微信和填写姓名)祝福所有程序员幸福快乐...

    [实例简介] HTML5春节(支持微信和填写姓名)祝福所有程序员幸福快乐 [实例截图] [核心代码] chunjie └── chunjie ├── cjold_m.css ├── index.htm ...

  7. 做柜员还是程序员_程序员放弃互联网选择去银行,但想到同学工资高好几倍心里不平衡...

    原标题:程序员放弃互联网选择去银行,但想到同学工资高好几倍心里不平衡 一名程序员在论坛上表达了自己内心的苦恼与失落:放弃了一线的互联网大厂去银行做技术,以后还怎么平衡身边同学工资是自己几倍的心理. 这 ...

  8. 程序员的快乐往往就是这么朴素无华且枯燥!

    作者 | 程序员小吴 来源 | 五分钟学算法 前几天在头条和知乎写了个段子,居然收获了 10w+ 的阅读,今天分享给大家. 程序员的快乐往往就是这么朴素无华且枯燥! 我,打开了 LeetCode 官网 ...

  9. 『设计模式』Web程序开发最基本的编程模式--MVC编程模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 什么是MVC编程模式 ? MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controlle ...

  10. 『设计模式』之小试牛刀

    为了更好的学习设计模式,以及督促自己完成设计模式的学习,现提笔为记. 怎么的,每周至少也要学一个设计模式!!! 恳请大家的监督和不吝赐教,共同学习和进步! 内容主要参考自<设计模式之禅>以 ...

最新文章

  1. Visualizing A Neural Machine Translation Model (Mechanics of Seq2seq Models With Attention)
  2. CentOS7配置iptables防火墙
  3. 12 信息2班 《基于Android的软件开发》课程成绩
  4. Scrapy-xpath用法以及实例
  5. 动态鼠标指针_推荐8款电脑鼠标指针,让你电脑不再千篇一律
  6. 开年赢好运!程序员加油包等你免费拿
  7. springboot的redis工具类编写(采用RedisTemplate)(简单的取值,取多个值)。
  8. [nRF51822] 3、 新年也来个总结——图解nRF51 SDK中的Button handling library和FIFO library...
  9. fieldset ----- 不常用的HTML标签
  10. java mac pos_pos终端mac国密(sm4)算法(java实现)
  11. spring data elasticsearch 对应 elasticsearch 版本
  12. 发布中文搜索引擎数据库 TngouDB
  13. 中兴通讯与寒武纪合作 加速5G时代边缘智能
  14. 新手电脑硬件软件故障解答(三)
  15. viper4android脉冲样本,v4a脉冲反馈样本官方版
  16. vue 子组件调用($emit)父组件方法后父组件方法如何回调子组件方法
  17. 终端 删除php文件内容,Mac_mac命令行终端可以卸载吗?mac命令行终端卸载软件教程,  mac os系统卸载软件方式有 - phpStudy...
  18. 单目标多目标优化算法的测试函数与解
  19. Arduino通过USB转TTL无BootLoader烧录程序的两种办法
  20. 汽车减速器设计及三维建模

热门文章

  1. html5实现圆圈里带一个三角形,CSS制作箭头图标代码(圆,三角形,椭圆)c
  2. 接口应用练习题(用接口的方式实现某网上商城的网上支付功能)
  3. HTML学习笔记05-文本格式化
  4. Openstack 之 调整nova相关参数
  5. 网易2016年研发project师编程题(2)
  6. 【酷熊科技】工作积累 ----------- 在unity3d里怎样隐藏物体
  7. setjump, longjump学习
  8. 如何修改远程桌面连接3389端口
  9. CodeForces 14E Camels :利用1-4拼成长为n的序列,使准确含有t个峰t-1个谷,求方案数 :dp...
  10. 在Linux中发现IP地址冲突的方法