面试官:如何在Integer类型的ArrayList中同时添加String、Character、Boolean等类型的数据?

开发 前端
程序在运行过程中发生由于硬件设备问题、软件设计错误等导致的程序异常事件。(在 Java 等面向对象的编程语言中)异常本身是一个对象,产生异常就是产生了一个异常对象。
  •  1、问题描述
  • 2、什么是异常
  • 3、异常体系分类
  • 4、反射的概述
  • 5、反射机制的作用
  • 6、反射的三种实现方式
  • 7、通过反射获取类的方法
  • 8、通过反射创建对象
  • 9、Method类的invoke()方法
  • 10、思路分享
  • 11、代码实现
  • 关于作者

1、问题描述

“如何在 Integer 类型的 ArrayList 中同时添加 String、Character、Boolean 等类型的数据?”

你是不是想到下面的代码?

  1. package com.cya.test; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5.  
  6. public class Test{ 
  7.  
  8.     public static void main(String []args){ 
  9.  
  10.         List<Integer> list=new ArrayList<>(); 
  11.         Integer in=1; 
  12.         Character ch='c'
  13.         Boolean bo=true
  14.         list.add(in); 
  15.         list.add(ch); 
  16.         list.add(bo); 
  17.         System.out.println(list); 
  18.  
  19.     } 
  20.  

有点 Java 基础的人都知道上面的代码运行会报错,如果使用 Eclipse等开发工具的话在没运行之前就会提示有错了,如下图:

强制运行一波,看下错误提示:

  1. Exception in thread "main" java.lang.Error: Unresolved compilation problems:  
  2.     The method add(Integerin the type List<Integeris not applicable for the arguments (Character
  3.     The method add(Integerin the type List<Integeris not applicable for the arguments (Boolean) 
  4.  
  5.     at com.cya.test.Test.main(Test.java:15) 

听说英语差的都去当程序员了!!

不过没关系,能get到大体意思就好了,上面的错误大体意思如下:

程序在编译时遇到了无法解析的错误, add方法的参数是 Integer 类型,无法接收 Character 类型的参数, add方法的参数是 Integer 类型,无法接收 Boolean 类型的参数

上面代码错误的原因是程序无法通过编译,在编译期出现异常,这和 Java 是编译性语言(如:C、C++、Delphi、Pascal、Java)有关。与解释性语言(如:Basic、javascript、Python)不同,Java 先将后缀名为.java 的源代码文件编译成后缀名为 .class 的字节码文件,编译期间会进行词法、语法、数据类型、语义分析。上面的错误就是在编译期间进行数据类型分析时类型不匹配造成的。

谈到这里,我们不得不提下 Java 的异常体系,异常体系结构图如下:

2、什么是异常

程序在运行过程中发生由于硬件设备问题、软件设计错误等导致的程序异常事件。(在 Java 等面向对象的编程语言中)异常本身是一个对象,产生异常就是产生了一个异常对象。

3、异常体系分类

如上面的 Java 异常体系结构图所示,Throwable有两个重要的子类:Exception(异常)和 Error(错误),两者都包含了大量的异常处理类。

(一)Error(错误)

程序中无法处理的错误,表示运行应用程序中出现了严重的错误。此类错误一般表示代码运行时 JVM 出现问题。通常有 Virtual MachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如说当JVM 耗完可用内存时,将出现 OutOfMemoryError。此类错误发生时,JVM 将终止线程。

这些错误是不可查的,非代码性错误。因此,当此类错误发生时,应用不应该去处理此类错误。

(二)Exception(异常)

程序本身可以捕获并且可以处理的异常。

Exception 这种异常又分为两类:运行时异常和编译异常。

  • 运行时异常(不受检异常):RuntimeException 类及其子类表示 JVM 在运行期间可能出现的错误。比如说试图使用空值对象的引用(NullPointerException)、数组下标越界(ArrayIndexOutBoundException)。此类异常属于不可查异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。
  • 编译异常(受检异常):Exception 中除 RuntimeException及其子类之外的异常。如果程序中出现此类异常,比如说 IOException,必须对该异常进行处理,否则编译不通过。在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类。

看完了Java的异常体系,我们知道上面代码出现的异常为编译时异常,是必须要处理的,否则无法通过编译阶段,更不要谈运行了。

既然上面代码不可用,那就请出本期的主角--- Java 的反射机制。

4、反射的概述

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

5、反射机制的作用

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;

在运行时调用任意一个对象的方法;

6、反射的三种实现方式

  • 通过对象的 getClass() 方法。getClass() 方法是 Object 类的方法,因为所有类都继承自 Object 类,所以可以直接使用 getClass() 方法。
  • 通过类名 .class 属性。如果知道类的名称,可以直接获取一个类的 Class。
  • 通过 Class 类的 forName(parameter) 方法(常用)。这种方式是最常用的,在各类框架的配置文件中可以看到,如:Spring、SpringMVC、Mybatis 等等。其中,参数 parameter 为全限定类名(即:包名+类名),如:com.cya.test.Test。

7、通过反射获取类的方法

方法名称 返回值 参数 说明
getMethods() Method [] 获取包括自身和继承过来的所有的public方法
getDeclaredMethods() Method [] 获取自身类中所有的方法(不包括继承的,和访问权限无关)
getMethod(String methodName,Class<?>... parameterTypes) Method methodName:表示被获取方法的名字parameterTypes:表示被获取方法的参数的Class类型,如String.class 表示获取指定的一个公共的方法(包括继承的)
getDeclaredMethod(String methodName,Class<?>... parameterTypes) Method methodName:表示被获取方法的名字parameterTypes:表示被获取方法的参数的Class类型,如 String.class 表示获取指定的一个本类中的方法(不包括继承的)

8、通过反射创建对象

Java 中,除了使用new关键字创建对象外,也可以用 newInstance() 方法创建对象,例如:

  1. Class class1 = Class.forName("java.util.ArrayList"); 
  2. List list=(List)class1.newInstance(); 

9、Method类的invoke()方法

public Object invoke(Object obj,Object args[])

作用:动态调用 Method 类代表的方法

obj:从中调用底层方法的对象,必须是实例化的对象

args:用于方法调用的参数,是个 Object 数组,因为参数有可能有多个

obj 可以为空,但必填 null,表示同类中的公用方法

args 参数可以为空,就是对应方法没有参数

有关 Java 反射的详细内容我将会专门出一期来讲解,这里只对本期用到的几个重要的知识点做概述。

看完了上面的内容,你是不是对面试官的问题有解答思路了呢?下面给出小编自己的想法,如果你有更好的方法,记得跟大家分享哦。

10、思路分享

创建 Integer 类型的 List 集合,用于存放数据。

使用对象名 .getClass() 方法获取 Class 对象。

调用 getMethod() 方法获取指定的 Method。

调用 invoke() 方法将不同数据类型的数据添加到 list 集合中。

11、代码实现

  1. package com.cya.test; 
  2.  
  3. import java.lang.reflect.Method; 
  4. import java.util.ArrayList; 
  5. import java.util.List; 
  6.  
  7. public class Test{ 
  8.  
  9.     public static void main(String []args) throws Exception{ 
  10.  
  11.         List<Integer> list=new ArrayList<>(); 
  12.         Object o; 
  13.  
  14.         //向list中添加Integer类型的数据 
  15.         Integer integer=1; 
  16.         o=integer
  17.         Test.addObjectToList(list, o); 
  18.  
  19.         //向list中添加String类型的数据 
  20.         String string="Hello World"
  21.         o=string; 
  22.         Test.addObjectToList(list, o); 
  23.  
  24.         //向list中添加Character类型的数据 
  25.         Character character='c'
  26.         o=character
  27.         Test.addObjectToList(list, o); 
  28.  
  29.         //向list中添加Boolean类型的数据 
  30.         Boolean boolean1=true
  31.         o=boolean1; 
  32.         Test.addObjectToList(list, o); 
  33.  
  34.         System.out.println(list); 
  35.  
  36.     } 
  37.  
  38. public static List<Integer> addObjectToList(List<Integer> list, Object o) throws Exception{ 
  39.  
  40.         Class class1=list.getClass(); 
  41.         Method method=class1.getMethod("add", Object.class); 
  42.         method.invoke(list, o); 
  43.         return list; 
  44.     } 
  45.  

关于作者

作者: C you again,从事软件开发 努力在IT搬砖路上的技术小白。

本文转载自微信公众号「C you again」,可以通过以下二维码关注。转载本文请联系C you again公众号。

 

责任编辑:武晓燕 来源: C you again
相关推荐

2021-02-25 07:08:30

JavaScript 前端面试题

2023-09-01 15:27:31

2015-08-13 10:29:12

面试面试官

2020-12-01 11:50:49

数据库Redis面试

2021-08-24 08:05:41

泛型类型擦除Class

2024-02-01 08:08:53

Spring过滤器类型Gateway

2010-08-12 16:28:35

面试官

2021-07-06 07:08:18

管控数据数仓

2019-07-16 10:10:46

JavaScript数据类型

2021-09-15 07:56:32

TypeScriptVue项目

2021-09-14 07:06:13

React项目TypeScript

2020-09-17 17:53:12

面试ArrayList数组

2019-08-12 15:40:26

Redis数据库数据类型

2018-10-22 14:28:26

面试官数据公司

2023-02-16 08:10:40

死锁线程

2021-09-09 07:21:26

TypeScript 高级类型

2020-08-06 07:49:57

List元素集合

2020-09-30 06:49:25

MySQL查询删除

2015-08-24 09:00:36

面试面试官

2024-02-04 10:08:34

点赞
收藏

51CTO技术栈公众号