文档开发者中心
我的

动态加载不适合数组类?那如何动态加载一个数组类?

摘要:既然数组是一个类,那么编译后类名是什么?类路径呢?为什么说动态加载不适合数组?那应该如何动态加载一个数组?

本文分享自华为云社区《【JAVA冷知识】动态加载不适合数组类?那如何动态加载一个数组类?》,作者:山河已无恙。

  • 今天和小伙伴分享一些java小知识点,主要围绕下面几点:
  • 既然数组是一个类,
  • 那么编译后类名是什么?类路径呢?
  • 为什么说动态加载不适合数组?
  • 那应该如何动态加载一个数组?
  • 部分内容参考
    • 《编写高质量代码(改善Java程序的151个建议)》
    • 《深入理解Java虚拟机》

一、既然数组是一个类,那么编译后类名是什么?

通下面的代码我们可以看出,对于基本类型数组,编译后为[+基本类型标识,对于引用类型为[L+引用类类路径

收起
自动换行
深色代码主题
复制

package com.liruilong;import java.util.logging.Logger;/*** @Project_name: workspack* @Package: com.liruilong* @Description:* @Author: 1224965096@qq.com* @WeChat_Official_Accounts: 山河已无恙* @blog: https://liruilong.blog.csdn.net/* @Date: 2022/2/9 3:08*/public class ArrayDemo {static Logger logger = Logger.getAnonymousLogger();public static void main(String[] args) {logger.info("基本类型数组编译后类名:" + int[].class.getName());logger.info("引用类型数组编译后类名:" + String[].class.getName());}}
收起
自动换行
深色代码主题
复制

二月 09, 2022 3:57:03 上午 com.liruilong.ArrayDemo main信息: 基本类型数组编译后类名:[I二月 09, 2022 3:57:03 上午 com.liruilong.ArrayDemo main信息: 引用类型数组编译后类名:[Ljava.lang.String;Process finished with exit code 0

在java中数组是一个较为特殊的类,不管是基本类型数组,还是引用类型数组,都没有可追溯的类路径

数组元素类型及编译后的类型

元素类型

编译后的类型

byte[]

[B

char[]

[C

Double[]

[D

Float[]

[F

Int[]

[I

Long[]

[J

Short[]

[S

Boolean

[Z

引用类型(如String)

[L引用类型

二、为什么动态加载不适合数组

动态加载

关于动态加载,这里不多讲,相信小伙伴么都不陌生,在原始的JDBC编程连接数据库的时候,通常会通过静态块动态的加载一个连接数据库的驱动类,这里会用到Class.forName(driver),将驱动类加载到内存中。

当然这里forName只是把一个类加载到内存中,并不是产生一个实例对象,也不会执行任何方法,具体的注入的驱动类如何生成对象,如何注册到DriverManager,一般可以通过静态块的方式实现,即类加载的同时生成实例对象并注册。

我们知道在类加载(加载,验证,准备,解析,初始化)的最后一步类初始化的时候,执行类构造器<clinit>()方法,<clinit>()方法是编译器自动收集类中的所有类变量的赋值动作的和静态语句块的中的语句合并产生的。编译器收集的顺序是由语句中源文件中出现的顺序决定。

下面是mysql驱动类的源码

收起
自动换行
深色代码主题
复制

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.mysql.jdbc;import java.sql.DriverManager;import java.sql.SQLException;public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}}

为什么不适合数组

关于动态加载,小伙伴可以看看《深入理解Java虚拟机》,回到我们的问题,为什么数组不适合动态加载,由上面的代码可以知道,当使用forName加载一个类时,需要一个类的全路径,或者说全限定名。

但是不管是基本类型数组,还是引用类型数组,都没有可追溯的类路径,不是一个具体的类,所以在加载的时候,会报错java.lang.ClassNotFoundException

收起
自动换行
深色代码主题
复制

package com.liruilong;import java.util.logging.Logger;/*** @Project_name: workspack* @Package: com.liruilong* @Description:* @Author: 1224965096@qq.com* @WeChat_Official_Accounts: 山河已无恙* @blog: https://liruilong.blog.csdn.net/* @Date: 2022/2/9 3:08*/public class ArrayDemo {static Logger logger = Logger.getAnonymousLogger();public static void main(String[] args) throws ClassNotFoundException {Class.forName("java.lang.String[]");Class.forName("int[]");}}Exception in thread "main" java.lang.ClassNotFoundException: java/lang/String[]at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:264)at com.liruilong.ArrayDemo.main(ArrayDemo.java:19)Process finished with exit code 1

直接加载不可以,那么加载一个数组编译后的类型是否可行呢?我们来看看

收起
自动换行
深色代码主题
复制

package com.liruilong;import java.util.logging.Logger;/*** @Project_name: workspack* @Package: com.liruilong* @Description:* @Author: 1224965096@qq.com* @WeChat_Official_Accounts: 山河已无恙* @blog: https://liruilong.blog.csdn.net/* @Date: 2022/2/9 3:08*/public class ArrayDemo {static Logger logger = Logger.getAnonymousLogger();public static void main(String[] args) throws ClassNotFoundException {Class.forName("[Ljava.lang.String;");Class.forName("[I");}}Bad level value for property: .levelBad level value for property: java.util.logging.ConsoleHandler.levelProcess finished with exit code 0

通过上面我们可以知道,可以加载编译后的类路径动态加载一个对象数组,但是没有意义。并不能通过newInstance()方法生成一个实例对象,在java中数组是定长的,没有长度的数组是不允许存在的。

收起
自动换行
深色代码主题
复制

package com.liruilong;import java.util.logging.Logger;/*** @Project_name: workspack* @Package: com.liruilong* @Description:* @Author: 1224965096@qq.com* @WeChat_Official_Accounts: 山河已无恙* @blog: https://liruilong.blog.csdn.net/* @Date: 2022/2/9 3:08*/public class ArrayDemo {static Logger logger = Logger.getAnonymousLogger();public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {Class<String[]> aClass = (Class<String[]>) Class.forName("[Ljava.lang.String;");String[] strings = aClass.newInstance();}}Bad level value for property: .levelBad level value for property: java.util.logging.ConsoleHandler.levelException in thread "main" java.lang.InstantiationException: [Ljava.lang.String;at java.lang.Class.newInstance(Class.java:427)at com.liruilong.ArrayDemo.main(ArrayDemo.java:20)Caused by: java.lang.NoSuchMethodException: [Ljava.lang.String;.<init>()at java.lang.Class.getConstructor0(Class.java:3082)at java.lang.Class.newInstance(Class.java:412)... 1 moreProcess finished with exit code 1

三、如何动态加载一个数组

那如何通过类似动态加载的方式生成一个数组,我们可以使用Array数组工具类来动态加载一个数组。

收起
自动换行
深色代码主题
复制

package com.liruilong;import java.lang.reflect.Array;import java.util.logging.Logger;/*** @Project_name: workspack* @Package: com.liruilong* @Description:* @Author: 1224965096@qq.com* @WeChat_Official_Accounts: 山河已无恙* @blog: https://liruilong.blog.csdn.net/* @Date: 2022/2/9 3:08*/public class ArrayDemo {static Logger logger = Logger.getAnonymousLogger();public static void main(String[] args) {String [] strings = (String[]) Array.newInstance(String.class,6);logger.info("String数组长度:"+strings.length);int[][] ints = (int [][])Array.newInstance(int.class,6,3);logger.info("int数组长度:"+ints.length);}}
收起
自动换行
深色代码主题
复制

Bad level value for property: .levelBad level value for property: java.util.logging.ConsoleHandler.levelCan't set level for java.util.logging.ConsoleHandler二月 09, 2022 5:15:12 上午 com.liruilong.ArrayDemo main信息: String数组长度:6二月 09, 2022 5:15:12 上午 com.liruilong.ArrayDemo main信息: int数组长度:6Process finished with exit code 0

看看源码,我们会发现这是一个本地方法,通过C或者C++之类的语言实现的

收起
自动换行
深色代码主题
复制

public static Object newInstance(Class<?> componentType, int length)throws NegativeArraySizeException {return newArray(componentType, length);}private static native Object newArray(Class<?> componentType, int length)throws NegativeArraySizeException;

关于数组的动态加载和小伙伴们分享到这里,生活加油哦 ^_^

点击关注,第一时间了解华为云新鲜技术~

点赞
收藏
回复
1
分享
举报
浏览303 发布于2022-02-11 03:29未知归属地
全部评论
最多点赞
最新发布
最早发布
看完感觉脑袋空空,什么都没留下
1楼回复于2022-02-11 10:44 未知归属地
写回答
新增插入模板功能
一键使用模板,快速填写内容,轻松发帖~
知道了
  • 为了保障您的信息安全,请勿上传您的敏感个人信息(如您的密码等信息)和您的敏感资产信息(如关键源代码、签名私钥、调试安装包、业务日志等信息),且您需自行承担由此产生的信息泄露等安全风险。
  • 如您发布的内容为转载内容,请注明内容来源。

我要发帖子

目录 收起
一、既然数组是一个类,那么编译后类名是什么?
二、为什么动态加载不适合数组
动态加载
为什么不适合数组
三、如何动态加载一个数组
了解社区公约,与您携手共创和谐专业的开发者社区。