[Java基础] java基础知识面试题系列汇总大全(二)

面试亮剑 面试亮剑 8309 人阅读 | 0 人回复

数组有没有 length()方法?String 有没有 length()方法?

数组没有 length()方法,有 length 的属性。

String 有 length()方法。

JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

在 Java 中,如何跳出当前的多重嵌套循环?

在最外层循环前加一个标记如 A,然后用 break A;可以跳出多重循环。

(Java 中支持带标签的 break 和 continue 语句,作用有点类似于 C 和 C++中的 goto 语句,但是就像要避免使用 goto 一样,应该避免使用带标签的 break 和 continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好)

构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载

两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

不对

如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希码(hash code)应当相同。

Java 对于 eqauls 方法和 hashCode 方法是这样规定的:

(1)如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;

(2)如果两个对象的 hashCode 相同,它们并不一定相同。

当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在 Set 集合中

同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

补充:

首先 equals 方法必须满足

自反性(x.equals(x)必须返回 true) 对称性(x.equals(y)返回 true 时,y.equals(x)也必须返回 true)

传递性(x.equals(y)和 y.equals(z)都返回 true 时,x.equals(z)也必须返回 true)

一致性(当 x 和 y 引用的对象信息没有被修改时,多次调用 x.equals(y)应该得到同样的返回值),而且对于任何非 null 值的引用 x,x.equals(null)必须返回 false。

实现高质量的 equals 方法的诀窍包括:

  1. 使用==操作符检查”参数是否为这个对象的引用”;
  2. 使用 instanceof 操作符检查”参数是否为正确的类型”;
  3. 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;
  4. 编写完 equals方法后,问自己它是否满足对称性、传递性、一致性;
  5. 重写 equals 时总是要重写 hashCode;
  6. 不要将 equals 方法参数中的 Object 对象替换为其他的类型,在重写时不要忘掉@Override 注解

是否可以继承 String 类?

String 类是 final 类,不可以被继承

继承 String 本身就是一个错误的想法,对 String 类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

值传递。

Java 语言的方法调用只支持参数的值传递。

当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。

对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。

C++和 C#中可以通过传引用或传输出参数来改变传入的参数的值。

String 和 StringBuilder、StringBuffer 的区别?

Java 平台提供了两种类型的字符串:

String 和 StringBuffer/StringBuilder

它们可以储存和操作字符串。

其中 String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。

而 StringBuffer/StringBuilder 类表示的字符串对象可以直接进行修改。

StringBuilder 是 Java 5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized 修饰,因此它的效率也比 StringBuffer 要高。

重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;

重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。

重载对返回类型没有特殊的要求

为什么不能根据返回类型来区分重载呢?

比如

int a();
double a();

如果是下面的形式,编译器还有机会推断应该调用哪个方法,但是如果都没有变量来接收调用结果,直接的调用,那么应该调用哪个方法呢?

int x  = a();

描述一下 JVM 加载 class 文件的原理机制?

JVM 中类的装载是由类加载器(ClassLoader)和它的子类来实现的

Java 中的类加载器是一个重要的 Java 运行时系统组件,它负责在运行时查找和装入类文件中的类

由于 Java 的跨平台性,经过编译的 Java 源程序并不是一个可执行程序,而是一个或多个类文件。

当 Java 程序需要使用某个类时,JVM 会确保这个类已经被加载、连接(验证、准备和解析)和初始化。类的加载是指把类的.class 文件中的数据读入到内存中,通常是创建一个字节数组读入.class 文件,然后产生与所加载类对应的 Class 对象。

加载完成后,Class 对象还不完整,所以此时的类还不可用。

当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤。

最后 JVM 对类进行初始化,包括:

1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类;

2)如果类中存在初始化语句,就依次执行这些初始化语句。

类的加载是由类加载器完成的,类加载器包括:

根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器

(java.lang.ClassLoader 的子类)。

从 Java 2(JDK 1.2)开始,类加载过程采取了父亲委托机制(PDM)。

PDM 更好的保证了 Java 平台的安全性,在该机制中,JVM 自带的 Bootstrap 是根加载器,其他的加载器都有且仅有一个父类加载器。

类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。

JVM 不会向 Java 程序提供对 Bootstrap 的引用。下面是关于几个类 加载器的说明:

Bootstrap:

一般用本地代码实现,负责加载 JVM 基础核心类库(rt.jar); Extension:

从 java.ext.dirs 系统属性所指定的目录中加载类库,它的父加载器是 Bootstrap; System:

又叫应用类加载器,其父类是 Extension。它是应用最广泛的类加载器。

它从环境变量 classpath 或者系统属性 java.class.path 所指定的目录中记载类,是用户自定义加载器的默认父加载器

char 型变量中能不能存贮一个中文汉字,为什么?

char 类型可以存储一个中文汉字,因为 Java 中使用的编码是 Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个 char 类型占 2 个字节(16 比特),所以放一个中文是没问题的。

使用 Unicode 意味着字符在 JVM 内部和外部有不同的表现形式,在 JVM内部都是 Unicode,当这个字符被从 JVM 内部转移到外部时(例如存入文件系统中),需要进行编码转换。

所以 Java 中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如 InputStreamReader 和 OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承担了编码转换的任务;

抽象类(abstract class)和接口(interface)有什么异同?

抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用。

一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。

接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。

抽象类中的成员可以是 private、默认、protected、public 的,而接口中的成员全都是 public 的。

抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。

有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法

静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?

Static Nested Class 是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。

而通常的内部类需要在外部类实例化后才能实例化

Java 中非静态内部类对象的创建要依赖其外部类对象,如果说没有所谓的外部类对象,那么无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做: new Outer().new Inner();

Java 中会存在内存泄漏吗,请简单描述。

理论上 Java 因为有垃圾回收机制( GC)不会存在内存泄露问题(这也是 Java 被广泛使用于服务器端编程的一个重要原因);

然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被 GC 回收 ,因此也会导致内存泄露的发生 。

例 如 Hibernate 的 Session( 一级缓存 )中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象 ,如果不及时关闭(close)或清空( flush)一级缓存就可能导致内存泄露。

抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被 synchronized修饰?

都不能。

抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。

本地方法是由本地代码(如 C 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。

synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

静态变量和实例变量的区别

静态变量是被 static 修饰符修饰的变量,也称为类变量,它属于类

不属于类的任何一个对象

一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。

静态变量可以实现让多个对象共享内存。

补充:

在 Java 开发中,上下文类和工具类中通常会有大量的静态成员

是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

不可以

静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。

如何实现对象克隆?

有两种方式: 1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法; 2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常 ,这种是方案明显优于使用 Object 类的 clone 方法克隆对象。

让问题在编译的时候暴露出来总是好过把问题留到运行时。

GC 是什么?为什么要有 GC?

GC 是垃圾收集的意思

内存处理是编程人员容易出现问题的地方 ,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃

Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放 已分配内存的显示操作方法。

Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。

要请求垃圾收集,可以调用下面的方法之一:

System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以屏蔽掉显式的垃圾回收调用。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。

垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。

在 Java 诞生初期,垃圾回收是 Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东西。

移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性。

String s = new String(“xyz”);创建了几个字符串对象?

需要两个对象,一个是静态区的 ” xyz” ,一个是用 new 创建在堆上的对象。

但是如果"xyz" 已经在静态区存在了,那么实际只需要创建一个。

接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?

接口可以继承接口,而且支持多重继承。

抽象类可以实现 (implements)接口,抽象类可继承具体类也可以继承抽象类

一个”.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?

可以

但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致

Anonymous Inner Class(匿名内部类)是否可以继承其它类?是否可以实现接口?

可以继承其他类或实现其他接口,在 Swing 编程和 Android 开发中常用此方式来实现事件监听和回调

内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

Java 中的 final 关键字有哪些用法?

(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写;

(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

日期相关

Java 的时间日期 API 一直以来都是被诟病的东西,为了解决这一问题,Java8 中引入了新的时间日期 API,其中包括 LocalDate、LocalTime、LocalDateTime、Clock、Instant 等类,这些的类的设计都使用了不变模式,因此是线程安全的设计。

之前的那些如Calendar,就忘记他吧~

昨天的这一时刻:


public static void main(String[] args) {
  LocalDateTime today = LocalDateTime.now();
  LocalDateTime yesterday = today.minusDays(1);
  System.out.println(yesterday);
}
关注下面的标签,发现更多相似文章
    黄小斜学Java

    疯狂的字节X

  • 目前专注于分享Java领域干货,公众号同步更新。原创以及收集整理,把最好的留下。
    包括但不限于JVM、计算机科学、算法、数据库、分布式、Spring全家桶、微服务、高并发、Docker容器、ELK、大数据等相关知识,一起进步,一起成长。
热门推荐
海康摄像头接入 wvp-GB28181-pro平台测试验
[md]### 简介 开箱即用的28181协议视频平台 `https://github.c
[CXX1300] CMake '3.18.1' was not
[md][CXX1300] CMake '3.18.1' was not found in SDK, PATH, or
[若依]微服务springcloud版新建增添加一个
[md]若依框架是一个比较出名的后台管理系统,有多个不同版本。