Java学习打卡:第二十二天

内容导航

  • Java学习打卡:第二十二天
    • 内容管理
      • Java反射机制
        • 问题引入---数据库介绍
        • Java反射的介绍
          • class的使用
          • 由字符串产生类和对象
          • 获取一个类的所有构造方法的字节码
          • 获取一个类的方法(也可以忽略访问权限)
      • 反射的总结

Java养成计划(打卡第22天)


内容管理

排除学业过于繁忙的时间还有昨天娱乐停更,我们的分享文章已经进行到了22天,再前面的时间里我们一直再扎实java SE的基础,当然这些基础是非常重要的,今天和大家分享的是Java的反射机制,当然这个模块的内容是十分庞大的,我们会慢慢分享

我们开始今天的内容:Java反射机制

Java反射机制

问题引入—数据库介绍

在说反射机制之前,我们知道计算机将数据存储在数据库里面,数据库就像是一个仓库一样,我们常见的数据库是Oracle,MySQL,DB2,SQLSever,SQLLite -----关系型数据库;Redis,MongoDB,HBase-----非关系型数据库

大概分析一下

  • SQLLite ,是Apache旗下的一款微型数据库,它所存储的数据非常小,占用内存也很小,相比Oracle就很小,它的应用场景就是比如手机等嵌入式设备,在实际开发中用到的比较少
  • DB2,是IBM旗下的数据库,市场占有率不高,主要应用于金融领域,所以开发中还是使用的比较少
  • SQLServer:微软旗下数据库,SQLsever因此与C/C++的兼容性更高,在Java中使用就需要做很多准备工作,所以在java中也很少使用
  • MySQL:也是Apache,是轻量级,并且是免费的,所以很多公司都会使用
  • Oracle:正量级,存储量庞大,但是会收费,并且所占内存大

现在的问题是,一个公司随着业务的扩大需要将所有与MySQL绑定的Java业务全部换成存储量更大的Oracle,你发现java业务中一共几千个文件,那难道要累死累活几天一个个点开文件,将所有的MySOL改成Oracle? 那效率太低下了

集群:一堆完成同一功能的服务器搭建的架构

比如现在用50台服务器作为数据库存储,那用MySOL又划算了,像再把Oracle换成MySOL,这时的文件规模估计又大了许多,所以再点开文件一个一个修改就不可行了

实际上这个绑定不是直接绑定的,在实际开发中往往是采用了Strategy模式,面向接口编程,既然有很多数据库类型,那就不要直接定义成普通类

数据处理部分Service -----操作数据库接口Dao(定义了所有操作数据库的方法)----Dao的具体实现(mySQLDao)-------MySOL

我们在service中就会定义接口的实现类 Dao d = new OracleDao();上转型变量,实现多态,所以这就是所谓的绑定,我么如果真修改就是将所有代码中的子类对象给修改了

这就是 耦合–两个模块之间相互关联

所以说耦合在实际开发中要解耦

那怎么解耦呢,我们可以定义一个文件dao.properties,在这个文件中我们写入dao = MySOLDao;

我们调用实现类对象时就不直接创建对象了,我们就直接读取dao.proprties文件,根据文件内容来创建实现类对象

那这里我们读取到的是文件中的字符串,如何根据字符串来判定我们到底创建哪类对象呢?这就利用到了反射机制

反射机制就是将文件中的内容映射成类

Java反射的介绍

万物皆可对象

我们知道Java文件编译后称为字节码的文件,那这个字节码就可以抽象成类,而字节码是由类得到的,所以我们就可以抽象出

  • Class -------代表类的类
  • Package-------代表包的类
  • Method ------代表方法的类
  • Filed-------代表属性的类
  • Constructor-----代表构造方法的类
  • Annotation------代表注解的类

反射:在获取这个类的字节码的基础上来解剖这个类

我们既然知道这是类,怎么使用,如果直接创建对象 new,那么是会报错的,因为这个位于lang包的类代表的是类的类,所以它创建出的对象都是代表一个具体的类,new出来的对象是没有意义的,那我们要如何使用class

class的使用

class是对字节码的抽象,那么某一个具体的类的字节码是不是就是Class的实例码呢,那我们就直接定义一个Class变量,之后将某个具体的类的字节码赋值,那就可以得到具体的类了

public class Luogu extends Thread{public static void main(String[] args) {Class<String> stz = String.class;//接受类的字节码,这里<>里和后面都是某个具体的类System.out.println(stz);}
}

得到的结果就是

class java.lang.String

这里就获取到String类的字节码了

那接口可以吗,比如传入List;

也可以的

class java.awt.List //这里它调取了另外一个List

public class Luogu extends Thread{public static void main(String[] args) {Class<Listener> stz= Listener.class;System.out.println(stz);}
}

interface java.net.http.WebSocket$Listener

那除了类和接口,那数组可不可以获取字节码呢也是可以的

Class<int[]> stz = int[].class;

得到的结果是

class [I

从这个结果我们可以看出数组也是一个类,所以数组变量也是和其他类的一样都是对象变量

我们获取Class对象–实例码的方式

  • 像上面的演示一样利用.class的方式
  • 利用Object类里面的getClass() 对象.getClass
Object o = "abs";
Class<Object> stz = o.getClass();//得到对象所对应的实例类的字节码
  • (上面两种方式都需要给到具体的类和对象才能知道实例码)

我们其实还可以**利用Class的forName方法来获取,直接通过字符串就能获取到字节码

Class<String> stz = (Class<String>)Class.forName("Date");

这里我们要求的式前后相同,所以要使用一个强制类型转换

但是会出现异常,因为直接给个类型,它找不到的

这里的解决办是我们直接给全路径

public static void main(String[] args) throws ClassNotFoundException {@SuppressWarnings("unchecked")Class<String> stz = (Class<String>)Class.forName("java.util.Date");System.out.println(stz);}

运行之后就可以打印出类所对应的字节码了

class java.util.Date

由字符串产生类和对象
  • 我们先利用Class的forname就可以得到一个字符串所对应的类
  • 之后利用存储类的字节码的变量使用.newInstance()方法,就可以按照无参的构造方法创建一个该类的一个实例对象,用一个该变量去接受(但是这里只能就使用无参的构造方法) 那我们要使用含参的构造方法就要使用上面的C欧尼structor类
Class<String> cla = (Class<String>)Class.forName("java.lang.String");
String str = Cla.newInstane();

这里我们如果正常创建一个Integer对象

Integer in = new Integer(5);

将对像设置为5;那我们就不能使用上的无参的newInstance了,这里就要使用Constructor了

Class<Integer> stz = (Class<Integer>)Class.forName("java.lang.Integer");Constructor<Integer> c = stz.getConstructor(int.class); //获取到了其构造方法Integer in = c.newInstance(5);//由构造方法初始化对象System.out.println(in);

这和上面的语句是等价的,这里我们就是将抽象方法也可以由字节码给反射,但是只能获取到非public的方法

那我们如何获取到非public的构造方法,这时就使用getDeclareConstructor();就可以获取了,传入所需要参数的字节码,就可以构造成功;

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException{      Class<String> stz = (Class<String>)Class.forName("java.lang.String");        Constructor<String> c = stz.getDeclaredConstructor(char[].class,boolean.class);      //Integer in = c.newInstance(5);       c.setAccessiable(true);//暴力破解,将非法变为合法        System.out.println(c.newInstance(new char[]{'a'}),true);  }

使用该方法就不用区分构造方法的访问权限,不管是public还是非public都可以使用

也就是说类中的访问权限修饰符在反射面前是无效的

获取一个类的所有构造方法的字节码

我们还可以直接使用getDclareConstructors获取类的所有构造方法;

比如String类的

@SuppressWarnings("rawtypes") public static void main(String[] args) {        Class<String> stz = String.class;        Constructor[] sc = stz.getDeclaredConstructors();      for(Constructor c:sc)//使用的for-each循环        {           System.out.println(c);      }   }

输出的结果是

public java.lang.String(byte[])
public java.lang.String(byte[],int,int)
public java.lang.String(byte[],java.nio.charset.Charset)
public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int,int,java.nio.charset.Charset)
java.lang.String(char[],int,int,java.lang.Void)
java.lang.String(java.lang.AbstractStringBuilder,java.lang.Void)
public java.lang.String(java.lang.StringBuilder)
public java.lang.String(java.lang.StringBuffer)
java.lang.String(byte[],byte)
public java.lang.String(char[],int,int)
public java.lang.String(char[])
public java.lang.String(java.lang.String)
public java.lang.String()
public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int)
public java.lang.String(byte[],int,int,int)
public java.lang.String(int[],int,int)

这就将String类的所有构造方法给打印出来了

获取一个类的方法(也可以忽略访问权限)

Method m = stz.getDeclaredMethod(“charAt”,int.class);

char c = (char) m.invoke(str,5);

反射的总结

上面杂七杂八说了很多,总的来说,反射就是我们可以通过字节码的方式反射出相应的类,方法,构造方法,属性等

  • 我们的获取类的字节码的方式有三种,一种是直接类名.class;还有就是由具体的对象获取 Object obj; obj.getClass就可以获取字节码;还有就是使用class类的forName方法,但是这种方法我们需要注意就是要将类名加在<>里,还有就是要给完全路径

  • 我们获取到类的字节码,我们就可以根据字节码获取到相关的Constructor,Method对象, 比如存储字节码的是stz, 那么通过stz.getDeclaredConstructor()就可以获取到相关的含参构造方法,对其实现就newInstance就可以使用

  • 同理我们使用方法也可以根据stz,stz.getDeclaredMethod()就可以获取方法,只是在获取方法时要传入参数的字节码,比如int.class ,String.class;实现就invoke()—传入具体的参数就可

  • 最关键的就是我们获取的方法都是不区分访问权限的,以前普通的方法或许存在不可见的问题,但是反射直接可以暴力破解 setAccessiable(true);这样我们就可以获取到私有的方法了

好了,今天的分享就到这里,感觉有些东西没有说清楚,明天会继续分析,望海涵~~

什么叫做类的类?如何获取私有的方法?Java反射机制太强大了,详解Java反射机制【Java养成】相关推荐

  1. python类继承中构造方法_第8.3节 Python类的__init__方法深入剖析:构造方法与继承详解...

    第8.3节Python类的__init__方法深入剖析:构造方法与继承详解 一.    引言 上两节介绍了构造方法的语法及参数,说明了构造方法是Python的类创建实例后首先执行的方法,并说明如果类没 ...

  2. java unsafe 详解_死磕 java魔法类之Unsafe解析

    问题 (1)Unsafe是什么? (2)Unsafe具有哪些功能? (3)Unsafe为什么是不安全的? (4)怎么使用Unsafe? 简介 本章是java并发包专题的第一章,但是第一篇写的却不是ja ...

  3. java双缓存机制_详解JVM类加载机制及类缓存问题的处理方法

    前言 大家应该都知道,当一个Java项目启动的时候,JVM会找到main方法,根据对象之间的调用来对class文件和所引用的jar包中的class文件进行加载(其步骤分为加载.验证.准备.解析.初始化 ...

  4. 《Java基础入门第2版》--黑马程序员 课后答案及其详解 第5章 Java中的常用类

    文章目录 一.填空题 二.判断题 三.选择题 四.简答题 五.编程题 六.原题及其解析 一.填空题 1. String.StringBuffer 2. Date.Calendar.DateFormat ...

  5. Java设计模式之原型模式最详解(类图+源码)

    原型模式 原型模式概述:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象. 原型模式包含的角色 抽象原型类:规定了具体原型对象必须实现的clone()方法. 具体原型类 ...

  6. getdatatable mysql_C# 自定义MySqlHelp类,包含了获取DataTable的方法,但是调用时总是提示“类型初始值设定项引发异常”...

    代码:classMySqlHelper{privatestaticstringconStr=ConfigurationManager.ConnectionStrings["conListOf ...

  7. Java Scaner类详解_动力节点Java学院整理

    Java.util.Scanner是Java5.0的新特征,主要功能是简化文本扫描.这个类最实用的地方表现在获取控制台输入,其他的功能都很鸡肋,尽管Java API文档中列举了大量的API方法,但是都 ...

  8. java继承类型的用法_详解Java中使用externds关键字继承类的用法

    理解继承是理解面向对象程序设计的关键.在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类).在Java中不允许多继承. (1)继承 cla ...

  9. python3类的继承详解_python3 多重继承机制

    由于python中包含多重继承机制,那么子类在多重继承中,到底用的是哪一个超类的方法就是大家关心的问题,之前在查阅已有书籍无果后,只得去翻官方文档与博客,终于得解,于是在此总结归纳. 全称 方法解析顺 ...

最新文章

  1. Cloneable接口和循环冗余校验算法
  2. json.dumps()函数解析
  3. Fiddler的学习
  4. 加密连接工具Cryptcat
  5. oracle 对象管理 01_用户及权限
  6. 基于Docker部署Nginx
  7. java 文件通配符_Java中泛型通配符的使用方法示例
  8. 关于完全删除电脑上多余的tomcat服务器的解决办法
  9. vsan的容量设备故障和缓存设备故障分析
  10. 安科瑞电气系统Acrel-2000在数据中心机房的应用及产品选型
  11. 统计学复习笔记(三)—— 置信区间(总体均值/比例/方差,总体均值之差/比例之差/方差之比)
  12. Live555实时视频流应用总结
  13. c语言狗追兔子,[转载]狗追兔典型例题
  14. 《东周列国志》第八十四回 智伯决水灌晋阳 豫让击衣报襄子
  15. 无聊吗,写个【飞机大战】来玩吧(下)
  16. 利用360安全卫士的“网络连接查看器”获取网络游戏的服务器IP地址
  17. 为什么要学习科学的方法论
  18. Java并发编程的艺术-并发编程基础
  19. java p44——Maven
  20. 【js学习笔记三十九】简单工厂模式

热门文章

  1. 【scrapy爬虫】crawl自动化模板爬取网易新闻
  2. 查找技巧,find及xargs的使用
  3. 【毕业设计】基于程序化生成和音频检测的生态仿真与3D内容生成系统----音频检测算法设计
  4. C语言printf格式化控制台移动光标
  5. Zemax自学--4(光学自动设计)
  6. 联想Lenovo M3410 驱动
  7. 百度-欢聚集团Joyy面经:22届 - Java开发实习生
  8. DTOJ #3316. baka
  9. iphone 开发随笔
  10. 分享:Word转PDF转换器有哪些?安利这3款好用工具