博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 面试题整理总结(一)Java 基础
阅读量:4293 次
发布时间:2019-05-27

本文共 7818 字,大约阅读时间需要 26 分钟。

目录

1、final 修饰一个对象,能否调用对象修改属性的方法?

2、fina l和 static关键字的区别?
3、static 修饰的方法可以被子类重写吗?为什么?
4、final、finally、finalize 分别表示什么含义?
5、抽象类能否实例化,理论依据是什么?
6、抽象类跟接口的区别,接口的默认修饰符?
7、面向对象编程的特点,多态性如何体现,Java虚拟机中的多态执行机制?
8、面向对象编程的四大特性及其含义?
9、重写和重载的区别?
10、谈谈对面向过程编程、面向对象编程还有面向切面编程的理解?
11、编译期注解跟运行时注解
12、注解如何获取,反射为何耗性能?
13、如何使用反射访问 private 数据?
14、什么是反射,有什么作用和应用?
15、int、long 的取值范围以及 BigDecimal,数值越界了如何处理?
16、Integer 类对 int 的优化?
17、装箱、拆箱什么含义?
18、int 和 Integer的区别?
19、简单介绍一下 Java 中的泛型,泛型擦除以及相关的概念?
20、String、StringBuffer 和 StringBuilder的区别?
21、String a="" 和 String a=new String("") 的关系和异同?
22、Java 是值传递还是引用传递?
23、Object 有哪些公用方法?
24、Object 的 equals 和 == 的区别?
25、为什么复写 equals 方法的同时需要复写 hashcode 方法,前者相同后者是否相同,反过来呢?为什么?
26、深拷贝和浅拷贝的区别
27、clone 的默认实现是深拷贝还是浅拷贝?如何让clone()实现深拷贝?
28、对 Java.nio 了解多少?
29、遇见过哪些运行时异常?异常处理机制知道哪些?
30、什么是内部类?有什么作用?静态内部类和非静态内部类的区别?
31、为什么匿名内部类中使用局部变量要用 final 修饰?

题解

1、final 修饰一个对象,能否调用对象修改属性的方法?

可以,final 修饰的是对应的引用,这意味着引用不可改变,即不可重新赋值,但对象内部的成员是可变的

2、fina l和 static关键字的区别?

final 修饰的对象不可重新赋值,static 修饰的对象是属于类本身的,即生命周期和类相同

3、static 修饰的方法可以被子类重写吗?为什么?

不行,子类如果实现了和父类名称和参数相同的 staitc 方法,只会隐藏父类的实现(隐藏的意思是:当这个 static 方法可见性为 protected、public 时,在子类访问这个方法,只会调用到子类自己的)。因为 static 修饰的方法是属于类本身的,而多态这一特性是针对单个对象而言的。

4、final、finally、finalize 分别表示什么含义?

final:修饰对象时,引用不可变;修饰基本数据类型时,值不可变;修饰类时,不可被继承;修饰方法时,不能被复写

finally:和 try-catch 配合使用,除非 JVM 终止,否则一定会被调用,常用于释放资源。但如果 try-catch 中执行了 return,则 finally 无法修改返回值

finalize:对象在回收时会被调用,只会被调用一次

5、抽象类能否实例化,理论依据是什么?

不能,抽象类是不完整的,某些方法可能只有声明,而没有定义(实现),调用这些方法会出现未知的结果

6、抽象类跟接口的区别,接口的默认修饰符?

个人理解,抽象类就像是一个模板,实现了子类共有的内容,剩下的部分交给子类自定义自己的实现;接口就像是一套规范,任何类都可以去按要求去实现这套规范。

即抽象类对类抽象,接口对行为抽象。

具体的区别如下:

  1. 方法实现。抽象类可以有已实现的方法;Java 8 之后接口也可以有默认方法和静态方法了
  2. 继承。子类用 extends 继承抽象类,只能继承一个,必须实现所有抽象方法,implements 实现接口,可以实现多个,必须实现所有已声明方法
  3. 构造器。抽象类可以有构造方法,接口不可以
  4. 抽象类除了不能实例化之外,和普通的类没有区别,接口则是完全不同的类型
  5. 访问修饰符。抽象类有 public、private 修饰符,接口默认方法都是 public 的(Java 9 可以有私有辅助方法),成员变量都是 public static final 的
  6. main 方法。抽象类可以有 main 方法,而且能够运行,接口不可以
  7. 速度。抽象类速度比接口稍快,因为接口需要去寻找类中实现的方法
  8. 添加新方法。抽象类可以添加新方法并给它默认的实现而子类不需要修改,接口则不行(Java 8 之后可以有默认方法)

7、面向对象编程的特点,多态性如何体现,Java 虚拟机中的多态执行机制?

面向对象的思想把一个问题分解成多个对象,然后使用这些对象互相配合以解决问题。可以提高程序的重用性、灵活性和可扩展性。

三个基本特征是封装、继承和多态。

实现多态的关键有 3 个:继承、重写、父类引用指向子类对象,它可以使程序具有良好的可扩展性,可以对类的所有对象进行通用处理,当改变对象的实际类型时,程序不需要做出其它改变。但不可以使用子类特有的成员变量和方法。

在 Java 虚拟机中,一切方法调用在 Class 文件里面存储的都只是符号引用,需要在类加载期间,甚至到运行期间才能确定目标方法的直接引用。多态之所以能够被实现,是由字节码指令 invokevirtual 的特性决定的,invokevirtual 指令会在运行时找到对象的实际类型,并调用对应的方法。而出于性能的考虑,大部分虚拟机会为类在方法区中建立一个虚方法表(invokeinterface 对应接口方法表),使用虚方法表来代替元数据查找以提高性能。

8、面向对象编程的三大特性及其含义?

继承:子类继承父类的特性和行为,是 is-a 关系,可以使得父类更通用,子类更具体

封装:将实现细节包装、隐藏起来的一种方法,比如 setter 和 getter,能够防止类的代码和数据被外部访问,从而减少耦合性,使得类更安全

多态:实现多态的关键有 3 个:继承、重写、父类引用指向子类对象,它可以使程序具有良好的可扩展性,可以对类的所有对象进行通用处理,当改变对象的实际类型时,程序不需要做出其它改变。但不可以使用子类特有的成员变量和方法。

9、重写和重载的区别?

重写:子类重写父类的方法,是实现多态的关键

重载:方法名相同,参数个数或类型不同

10、谈谈对面向过程编程、面向对象编程还有面向切面编程的理解?

// TODO 如果有更好的理解,欢迎指出

面向过程编程:将问题划分为多个步骤,一步一步实现以解决问题

面向对象编程: 把一个问题分解成多个对象,然后使用这些对象互相配合以解决问题。

面向切换编程:通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,可以在运行时(或者编译期、类加载时)动态地将代码切入到类的指定方法的指定位置上。

11、编译期注解跟运行时注解

编译期注解的信息会被编译器丢弃,可用于帮助编译器检查一些代码是否正确,比如 @IntDef

运行时注解的信息可以在运行时通过反射机制获取,比如 Dagger2、ButterKnife 等依赖注入框架就是通过运行时注解 + 反射机制实现的

12、注解如何获取,反射为何耗性能?

运行时注解的信息可以在运行时通过反射机制获取

由于反射涉及动态地解析类型,无法执行 Java 虚拟机的某些优化措施(比如 JIT?公共子表达式消除?数组范围检查消除?方法内联?逃逸分析?),因此性能低于非反射操作。如果是依赖注入,生成新的类时,还需要执行一遍类的加载过程(加载、验证、准备、解析、初始化)。

13、如何使用反射访问 private 数据?

public class ReflectPrivate {      private int a = 0;      public void test() {          System.out.println("ReflectPrivate: " + a);      }  }  public class Test {      public static void main(String[] args) {          ReflectPrivate reflectPrivate = new ReflectPrivate();          try {              Field field = reflectPrivate.getClass().getDeclaredField("a");              field.setAccessible(true);              field.setInt(reflectPrivate, 10);              reflectPrivate.test();          } catch (NoSuchFieldException | IllegalAccessException e) {              e.printStackTrace();          }      }  }

输出:

ReflectPrivate: 10

14、什么是反射,有什么作用和应用?

反射可以在运行时打开和检查 class 文件,从而获取类的某些信息

应用:Dagger2 等依赖注入框架

15、int、long 的取值范围以及 BigDecimal,数值越界了如何处理?

int:2^32

long:2^64

// TODO BigDenimal 未研究

BigDenimal:不限

基本数据类型溢出:按二进制处理

数组越界:抛出 ArrayIndexOutOfBoundsException

16、Integer 类对 int 的优化?

// TODO 优化指什么?

在常量池中缓存了 -128 ~ 127 的值

17、装箱、拆箱什么含义?

装箱:基本类型数据存储到集合或 Map 中的时候会自动转化为对应的装箱类型

拆箱:装箱类型赋值给基本数据类型时,类型会自动转换

18、int 和 Integer的区别?

int:基本数据类型,直接存数值,默认值为 0,使用 == 判断是否相等

Integer 是 int 的封装类,默认值为 null,使用 equals 判断是否相等

19、简单介绍一下 Java 中的泛型,泛型边界、泛型擦除的概念?

泛型可以把运行时的类型检查转换到编译时,消除了许多类型的强制转换,提高程序的安全性,同时增强了代码的可复用性,使得容器的使用十分方便

extends:上界匹配符,代表 T 及 T 的子类,适用于返回类型限定

super:下界匹配符,代表 T 及 T 的父类,适用于参数类型限定

泛型擦除:List 和 List 在运行时实际上是相同的类型——List,参数类型信息会被擦除,如果需要获取确切的参数类型,可以使用 Object 转型或反射创建对应的类型

20、String、StringBuffer 和 StringBuilder的区别?

String:不可变类,对 String 的任何改变都会生成新的对象,内部使用 char[] 实现,存储格式是 UTF-16

StringBuilder:内容可变,继承自 AbstractStringBuilder,线程不安全

StringBuffer:内容可变,继承自 AbstractStringBuilder,几乎所有成员方法都使用 synchronized 修饰,线程安全

21、String a="" 和 String b=new String("") 的关系和异同?

a 指向常量池引用,假如 “” 在常量池中已存在,那么 a 不会创建新的对象

new String 必定会创建一个新的对象,因此 a != b,但 a.equals(b) 为 true

22、Java 是值传递还是引用传递?

都是值传递,引用存储的是对象的地址,重新赋值会修改引用指向的地址,但原来的对象不会被改变

参考:

23、Object 有哪些公用方法?

  1. equals:用于自定义比较对象是否相等的逻辑

  2. hashCode:返回一个哈希值,该类对象作为 Map 容器的 Key 时,会通过这个方法确定存储该对象的数组的下标

  3. toString:用于自定义内容输出逻辑

  4. wait:用于等待某个条件满足时再向下执行,会释放对象的内置锁,唤醒后重新获取该对象锁

  5. notify:通知某个条件被满足了,正在等待同一对象锁的线程会被唤醒并向下执行

关于 Object 的通用方法的各种注意事项可以参考:

24、Object 的 equals 和 == 的区别?

== 用于比较引用地址是否相等

equals 用于自定义比较的逻辑,通常会通过比较 Object 的内部数据来判断是否相等

25、为什么复写 equals 方法的同时需要复写 hashcode 方法,前者相同后者是否相同,反过来呢?为什么?

equals 常用于比较内容是否相等

hashCode 用于返回一个哈希值,当该类的对象作为 Map 容器的 Key 时,这个哈希值代表的是存储该对象的数组的下标

equals 和 hashCode 需要同时复写

考虑到该类的对象在 Map 中作为 Key 的情况,如果只复写 equals 方法而没有复写 hashCode 方法,可能会导致程序运行结果不符合预期,例如:

  1. 有两个对象 A 和 B,equals 返回的结果相同,hashCode 返回的结果不同
  2. Map 在某个时刻将 A 作为 key,put 进了容器中
  3. Map 希望在另一个时刻容器中获取 key 为 A 的对象值,但此时无法获取到原来的对象 A 了,于是新建 B 作为 key 调用 get 方法,结果却返回 null 或另一个值

因为 HashMap 的运行机制是:先调用 hashCode 找到存储该对象的数组下标,接着遍历链表并逐个比较 hash 值和 equals 方法,都为 true 时即表明找到对应的元素了。因此,如果没有同时复写 equals 和 hashCode,可能无法在 HashMap 中查找到想要的对象,即使这个对象已经存储在 HashMap 里面。

26、深拷贝和浅拷贝的区别

深拷贝:拷贝出另一个一模一样的对象

浅拷贝:创建一个指向原对象的引用

27、clone 的默认实现是深拷贝还是浅拷贝?如何让clone()实现深拷贝?

默认浅拷贝

  1. 实现接口 Cloneable,让 clone 方法成为公有方法
  2. 在 clone 方法中首先调用 super.clone()
  3. 然后再逐个修改需要修改的域

注意:

  1. 修改过程中优先使用类库已有的方法,比如 List 等容器,可以先调用 clone,然后再修改
  2. 非基本数据类型的成员变量必须逐个修改,否则持有的是原引用

28、对 Java.nio 了解多少?

NIO(Non-blocking I/O,在 Java 领域,也称为 New I/O),是一种同步非阻塞的 I/O 模型,也是 I/O 多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。

  1. 旧的 I/O 包已经用 nio 重新实现过,因此即使不显式地用 nio 编写代码,也能从中受益

  2. NIO 速度地提高来自于所使用的结构更接近与操作系统控制 I/O 的方式:通道存储数据,缓冲器与通道进行通信

  3. 编写代码时不直接与通道交互,只和缓冲器交互

  4. 通道对应的接口是 Channel,有 FileChannel、SocketChannel 等实现类,唯一与通道交互的缓冲器是 ByteBuffer

参考:

29、遇见过哪些运行时异常?异常处理机制知道哪些?

常见异常 使用场合
IllegalArgumentException 参数(非 null)使用不正确
IllegalStateException 对象的状态不正确
NullPointerException 禁止使用 null 的情况下对象值为 null
IndexOutOfBoundsException 下标参数值越界
ConcurrentModificationException 禁止并发修改的情况下,检测到对象的并发修改
UnsupportedOperationException 对象不支持用户请求的方法

异常处理机制:

  1. 可抛出类型 Throwable有 两个子类——Error 和 Exception

    a) 其中 Error 代表编译时错误和系统错误,例如内存溢出、线程死锁等,程序本身无法克服和恢复
    b) Exception 是可以被抛出的基本类型,程序本身能够克服和恢复,是开发者需要关心的

  2. Exception 同样可以分为两类——不受检查的异常(运行时异常)和受检查的异常

    a) 运行时异常代表的是编程错误,自动被 Java 虚拟机抛出,所以不必在异常说明中列出来
    b) 其它异常称为受检查的异常,在编译器就变强制检查

  3. 异常链、异常查找顺序、子类父类、吞噬异常等可以自行网上查阅相关资料

30、什么是内部类?有什么作用?静态内部类和非静态内部类的区别?

内部类分为静态内部类和非静态内部类,非静态内部类又可以分为局部类、匿名类、普通(成员)内部类

非静态内部类的创建依赖于外围类,拥有一个隐式地指向外部类的引用,因此可以访问外围对象的所有成员,除了基本数据类型和 String 类型的 static final 变量外,不能存在 static 成员(包括变量、方法、内部类)

静态内部类的创建不依赖于外围类,不能访问外围对象的非静态成员,可以拥有 static 成员

作用:

  1. 解决了多重继承的问题
  2. 可以让多个内部类以不同的方式实现同一个接口,或继承同一个类
  3. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象地信息相互独立
  4. 成员内部类能够提供更好的封装,除了该外围类,其它类都不能访问

31、为什么匿名内部类中使用局部变量要用 final 修饰?

这是由 Java 的闭包实现机制决定的,闭包可以简单地认为是:

  1. 一个依赖于外部环境自由变量的函数
  2. 这个函数能够访问外部环境里的自由变量

Java 到处都是闭包,比如类的成员方法、内部类等,都是闭包。但 Java 编译器对闭包的支持不完整,它会偷偷地把外部局部变量复制一个副本到闭包里面,即 Java 编译器实现的只是 capture-by-value,并没有实现 capture-by-reference,而只有后者才能保持匿名内部类和外部环境局部变量保持同步。既然内外不能同步,Java 就干脆一刀切,不允许改变外部的局部变量。

参考:

转载地址:http://ejyws.baihongyu.com/

你可能感兴趣的文章
main函数带参数
查看>>
PCB布线技巧
查看>>
关于PCB设计中过孔能否打在焊盘上的两种观点
查看>>
PCB反推理念
查看>>
京东技术架构(一)构建亿级前端读服务
查看>>
git 提示:error: unable to rewind rpc post data - try increasing http.postBuffer
查看>>
php 解决json_encode中文UNICODE转码问题
查看>>
LNMP 安装 thinkcmf提示404not found
查看>>
PHP empty、isset、innull的区别
查看>>
apache+nginx 实现动静分离
查看>>
通过Navicat远程连接MySQL配置
查看>>
phpstorm开发工具的设置用法
查看>>
Linux 系统挂载数据盘
查看>>
Git基础(三)--常见错误及解决方案
查看>>
Git(四) - 分支管理
查看>>
PHP Curl发送数据
查看>>
HTTP协议
查看>>
HTTPS
查看>>
git add . git add -u git add -A区别
查看>>
apache下虚拟域名配置
查看>>