hey guys ,这不是也到了面试季了么,cxuan 又打算重新写一下 Java 相关的面试题,先从基础的开始吧,这些面试题属于基础系列,不包含多线程相关面试题和 JVM 相关面试题,多线程和 JVM 的我放在后面了,下面不多说,搞起!

Java 基础篇

Java 有哪些特点

  • 并发性的: 你可以在其中执行许多语句,而不必一次执行它
  • 面向对象的:基于类和面向对象的编程语言。
  • 独立性的: 支持一次编写,到处运行的独立编程语言,即编译后的代码可以在支持 Java 的所有平台上运行。

Java 的特性

Java 的特性有如下这几点

  • 简单,Java 会让你的工作变得更加轻松,使你把关注点放在主要业务逻辑上,而不必关心指针、运算符重载、内存回收等与主要业务无关的功能。
  • 便携性,Java 是平台无关性的,这意味着在一个平台上编写的任何应用程序都可以轻松移植到另一个平台上。
  • 安全性, 编译后会将所有的代码转换为字节码,人类无法读取。它使开发无病毒,无篡改的系统/应用成为可能。
  • 动态性,它具有适应不断变化的环境的能力,它能够支持动态内存分配,从而减少了内存浪费,提高了应用程序的性能。
  • 分布式,Java 提供的功能有助于创建分布式应用。使用远程方法调用(RMI),程序可以通过网络调用另一个程序的方法并获取输出。您可以通过从互联网上的任何计算机上调用方法来访问文件。这是革命性的一个特点,对于当今的互联网来说太重要了。
  • 健壮性,Java 有强大的内存管理功能,在编译和运行时检查代码,它有助于消除错误。
  • 高性能,Java 最黑的科技就是字节码编程,Java 代码编译成的字节码可以轻松转换为本地机器代码。通过 JIT 即时编译器来实现高性能。
  • 解释性,Java 被编译成字节码,由 Java 运行时环境解释。
  • 多线程性,Java支持多个执行线程(也称为轻量级进程),包括一组同步原语。这使得使用线程编程更加容易,Java 通过管程模型来实现线程安全性。

面向对象的特征有哪些

面向对象的特征主要有三点

  • 封装:封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

  • 继承:继承指的是使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

  • 多态:多态是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

JDK 和 JRE 有什么区别

  • JRE 的英文名称是 Java Runtime Environment,Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
  • JDK 的英文名称是 Java Development Kit,Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。

这里还需要解释一下 JVM 是什么

  • JVM 的英文名称是 Java Virtual Machine,指的就是 Java 虚拟机。Java 虚拟机是跨平台实现的核心

大致来说,JRE、JDK 和 JVM 的关系如下

描述一下值传递和引用传递的区别

要想真正理解的话,可以参考这篇文章 : https://www.zhihu.com/question/31203609

简单理解的话就是

值传递是指在调用函数时将实际参数复制一份到函数中,这样的话如果函数对其传递过来的形式参数进行修改,将不会影响到实际参数

引用传递 是指在调用函数时将对象的地址直接传递到函数中,如果在对形式参数进行修改,将影响到实际参数的值。

== 和 equals 区别是什么

== 是 Java 中一种操作符,它有两种比较方式

  • 对于基本数据类型来说, == 判断的是两边的是否相等
public class DoubleCompareAndEquals {
Person person1 = new Person(24,"boy");
Person person2 = new Person(24,"girl");
int c = 10; private void doubleCompare(){ int a = 10;
int b = 10; System.out.println(a == b);
System.out.println(a == c);
System.out.println(person1.getId() == person2.getId()); }
}
  • 对于引用类型来说, == 判断的是两边的引用是否相等,也就是判断两个对象是否指向了同一块内存区域。
private void equals(){
System.out.println(person1.getName().equals(person2.getName()));
}

equals 是 Java 中所有对象的父类,即 Object 类定义的一个方法。它只能比较对象,它表示的是引用双方的值是否相等。所以记住,并不是说 == 比较的就是引用是否相等,equals 比较的就是值,这需要区分来说的。

equals 用作对象之间的比较具有如下特性

  • 自反性:对于任何非空引用 x 来说,x.equals(x) 应该返回 true。
  • 对称性:对于任何非空引用 x 和 y 来说,若x.equals(y)为 true,则y.equals(x)也为 true。
  • 传递性:对于任何非空引用的值来说,有三个值,x、y 和 z,如果x.equals(y) 返回true,y.equals(z) 返回true,那么x.equals(z) 也应该返回true。
  • 一致性:对于任何非空引用 x 和 y 来说,如果 x.equals(y) 相等的话,那么它们必须始终相等。
  • 非空性:对于任何非空引用的值 x 来说,x.equals(null) 必须返回 false。

Java 中的基本数据类型有哪些,各自占用多少字节

在 Java 中,数据类型只有四类八种

  • 整数型:byte、short、int、long

byte 也就是字节,1 byte = 8 bits,byte 的默认值是 0 ;

short 占用两个字节,也就是 16 位,1 short = 16 bits,它的默认值也是 0 ;

int 占用四个字节,也就是 32 位,1 int = 32 bits,默认值是 0 ;

long 占用八个字节,也就是 64 位,1 long = 64 bits,默认值是 0L;

所以整数型的占用字节大小空间为 long > int > short > byte

  • 浮点型

浮点型有两种数据类型:float 和 double

float 是单精度浮点型,占用 4 位,1 float = 32 bits,默认值是 0.0f;

double 是双精度浮点型,占用 8 位,1 double = 64 bits,默认值是 0.0d;

  • 字符型

字符型就是 char,char 类型是一个单一的 16 位 Unicode 字符,最小值是 \u0000 (也就是 0 ),最大值是 \uffff (即为 65535),char 数据类型可以存储任何字符,例如 char a = 'A'。

  • 布尔型

布尔型指的就是 boolean,boolean 只有两种值,true 或者是 false,只表示 1 位,默认值是 false。

以上 x 位都指的是在内存中的占用。

String 中的 equals 是如何重写的

String 代表的是 Java 中的字符串,String 类比较特殊,它整个类都是被 final 修饰的,也就是说,String 不能被任何类继承,任何 修改 String 字符串的方法都是创建了一个新的字符串。

equals 方法是 Object 类定义的方法,Object 是所有类的父类,当然也包括 String,String 重写了 equals 方法,下面我们来看看是怎么重写的

  • 首先会判断要比较的两个字符串它们的引用是否相等。如果引用相等的话,直接返回 true ,不相等的话继续下面的判断
  • 然后再判断被比较的对象是否是 String 的实例,如果不是的话直接返回 false,如果是的话,再比较两个字符串的长度是否相等,如果长度不想等的话也就没有比较的必要了;长度如果相同,会比较字符串中的每个 字符 是否相等,一旦有一个字符不相等,就会直接返回 false。

下面是它的流程图

这里再提示一下,你可能有疑惑什么时候是

if (this == anObject) {
return true;
}

这个判断语句如何才能返回 true?因为都是字符串啊,字符串比较的不都是堆空间吗,猛然一看发现好像永远也不会走,但是你忘记了 String.intern() 方法,它表示的概念在不同的 JDK 版本有不同的区分

在 JDK1.7 及以后调用 intern 方法是判断运行时常量池中是否有指定的字符串,如果没有的话,就把字符串添加到常量池中,并返回常量池中的对象。

验证过程如下

private void StringOverrideEquals(){
String s1 = "aaa";
String s2 = "aa" + new String("a");
String s3 = new String("aaa"); System.out.println(s1.intern().equals(s1));
System.out.println(s1.intern().equals(s2));
System.out.println(s3.intern().equals(s1)); }
  • 首先 s1.intern.equals(s1) 这个无论如何都返回 true,因为 s1 字符串创建出来就已经在常量池中存在了。

  • 然后第二条语句返回 false,因为 s1 返回的是常量池中的对象,而 s2 返回的是堆中的对象

  • 第三条语句 s3.intern.equals(s1),返回 true ,因为 s3 对象虽然在堆中创建了一个对象,但是 s3 中的 "aaa" 返回的是常量池中的对象。

为什么重写 equals 方法必须重写 hashcode 方法

equals 方法和 hashCode 都是 Object 中定义的方法,它们经常被一起重写。

equals 方法是用来比较对象大小是否相等的方法,hashcode 方法是用来判断每个对象 hash 值的一种方法。如果只重写 equals 方法而不重写 hashcode 方法,很可能会造成两个不同的对象,它们的 hashcode 也相等,造成冲突。比如

String str1 = "通话";
String str2 = "重地";

它们两个的 hashcode 相等,但是 equals 可不相等。

我们来看一下 hashCode 官方的定义

总结起来就是

  • 如果在 Java 运行期间对同一个对象调用 hashCode 方法后,无论调用多少次,都应该返回相同的 hashCode,但是在不同的 Java 程序中,执行 hashCode 方法返回的值可能不一致。
  • 如果两个对象的 equals 相等,那么 hashCode 必须相同
  • 如果两个对象 equals 不相等,那么 hashCode 也有可能相同,所以需要重写 hashCode 方法,因为你不知道 hashCode 的底层构造(反正我是不知道,有大牛可以传授传授),所以你需要重写 hashCode 方法,来为不同的对象生成不同的 hashCode 值,这样能够提高不同对象的访问速度。
  • hashCode 通常是将地址转换为整数来实现的。

两个对象的 hashcode 相同,那么 equals 是否也一定为 true

这个肯定是不一定的,举个非常简单的例子,你重写了 hashcode 方法,来算取余数,那么两个对象的 hashcode 很可能重复,但是两个对象的 equals 却不一定相同。

就算你不重写 hashcode 方法,我给你一段代码示例

String str1 = "通话";
String str2 = "重地";
System. out. println(String. format("str1:%d | str2:%d", str1. hashCode(),str2. hashCode()));
System. out. println(str1. equals(str2));

上面两段代码的输出结果是

str1:1179395 | str2:1179395

false

这两个字符串的 equals 并不相同。也就是说,就算是 hashcode 相同的字符串,equals 也有可能不同。

String s1 = new String("abc") 在内存中创建了几个对象

一个或者两个,String s1 是声明了一个 String 类型的 s1 变量,它不是对象。使用 new 关键字会在堆中创建一个对象,另外一个对象是 abc ,它会在常量池中创建,所以一共创建了两个对象;如果 abc 在常量池中已经存在的话,那么就会创建一个对象。

详细请翻阅笔者的另外一篇文章 一篇与众不同的 String、StringBuffer、StringBuilder 详解

String 为什么是不可变的、jdk 源码中的 String 如何定义的、为什么这么设计。

首先了解一下什么是不可变对象,不可变对象就是一经创建后,其对象的内部状态不能被修改,啥意思呢?也就是说不可变对象需要遵守下面几条原则

  • 不可变对象的内部属性都是 final 的
  • 不可变对象的内部属性都是 private 的
  • 不可变对象不能提供任何可以修改内部状态的方法、setter 方法也不行
  • 不可变对象不能被继承和扩展

与其说问 String 为什么是不可变的,不如说如何把 String 设计成不可变的。

String 类是一种对象,它是独立于 Java 基本数据类型而存在的,String 你可以把它理解为字符串的集合,String 被设计为 final 的,表示 String 对象一经创建后,它的值就不能再被修改,任何对 String 值进行修改的方法就是重新创建一个字符串。String 对象创建后会存在于运行时常量池中,运行时常量池是属于方法区的一部分,JDK1.7 后把它移到了堆中。

不可变对象不是真的不可变,可以通过反射来对其内部的属性和值进行修改,不过一般我们不这样做。

static 关键字是干什么用的?谈谈你的理解

static 是 Java 中非常重要的关键字,static 表示的概念是 静态的,在 Java 中,static 主要用来

  • 修饰变量,static 修饰的变量称为静态变量、也称为类变量,类变量属于类所有,对于不同的类来说,static 变量只有一份,static 修饰的变量位于方法区中;static 修饰的变量能够直接通过 类名.变量名 来进行访问,不用通过实例化类再进行使用。
  • 修饰方法,static 修饰的方法被称为静态方法,静态方法能够直接通过 类名.方法名 来使用,在静态方法内部不能使用非静态属性和方法
  • static 可以修饰代码块,主要分为两种,一种直接定义在类中,使用 static{},这种被称为静态代码块,一种是在类中定义静态内部类,使用 static class xxx 来进行定义。
  • static 可以用于静态导包,通过使用 import static xxx 来实现,这种方式一般不推荐使用
  • static 可以和单例模式一起使用,通过双重检查锁来实现线程安全的单例模式。

深入理解请参考这篇文章 一个小小的 static 还能难得住我?

final 关键字是干什么用的?谈谈你的理解

final 是 Java 中的关键字,它表示的意思是 不可变的,在 Java 中,final 主要用来

  • 修饰类,final 修饰的类不能被继承,不能被继承的意思就是不能使用 extends 来继承被 final 修饰的类。
  • 修饰变量,final 修饰的变量不能被改写,不能被改写的意思有两种,对于基本数据类型来说,final 修饰的变量,其值不能被改变,final 修饰的对象,对象的引用不能被改变,但是对象内部的属性可以被修改。final 修饰的变量在某种程度上起到了不可变的效果,所以,可以用来保护只读数据,尤其是在并发编程中,因为明确的不能再为 final 变量进行赋值,有利于减少额外的同步开销。
  • 修饰方法,final 修饰的方法不能被重写。
  • final 修饰符和 Java 程序性能优化没有必然联系

抽象类和接口的区别是什么

抽象类和接口都是 Java 中的关键字,抽象类和接口中都允许进行方法的定义,而不用具体的方法实现。抽象类和接口都允许被继承,它们广泛的应用于 JDK 和框架的源码中,来实现多态和不同的设计模式。

不同点在于

  • 抽象级别不同:类、抽象类、接口其实是三种不同的抽象级别,抽象程度依次是 接口 > 抽象类 > 类。在接口中,只允许进行方法的定义,不允许有方法的实现,抽象类中可以进行方法的定义和实现;而类中只允许进行方法的实现,我说的方法的定义是不允许在方法后面出现 {}
  • 使用的关键字不同:类使用 class 来表示;抽象类使用 abstract class 来表示;接口使用 interface 来表示
  • 变量:接口中定义的变量只能是公共的静态常量,抽象类中的变量是普通变量。

重写和重载的区别

在 Java 中,重写和重载都是对同一方法的不同表现形式,下面我们针对重写和重载做一下简单的区分

  • 子父级关系不同,重写是针对子级和父级的不同表现形式,而重载是在同一类中的不同表现形式;
  • 概念不同,子类重写父类的方法一般使用 @override 来表示;重写后的方法其方法的声明和参数类型、顺序必须要与父类完全一致;重载是针对同一类中概念,它要求重载的方法必须满足下面任何一个要求:方法参数的顺序,参数的个数,参数的类型任意一个保持不同即可。

构造器能否被重载,能否被重写?

这道题考到你对于构造器的理解和认识。

我们 Java 中创建一个对象其实就是调用了该对象的构造方法,比如下面代码

InstanceObject IO = new InstanceObject() ; // 调用了无参构造方法
InstanceObject IO = new InstanceObject(xxx) ; // 调用了有参数的构造方法

而重载的概念是什么呢?

它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,JVM 就会根据不同的参数样式,来选择合适的方法执行

也就是说,重载的概念更多描述的是对相同命名的方法的不同描述。那么我们上面这段代码很显然就是重载了,因为名称相同,我可以通过有无参数来判断调用不同的构造方法来进行初始化。

那么构造器能否被重写呢?这里我们先来看一下什么是重写

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。从重写的概念定义来说我们就知道构造器不能被重写了。

首先,构造器没有返回值,第二点,构造器的名称必须和类名一致。

你总不能在类 A 中写了 public A();在类 B 中也写 public A() 吧,这显然是不能通过编译的。

byte的取值范围是多少,怎么计算出来的

byte 的取值范围是 -128 -> 127 之间,一共是 256 个。一个 byte 类型在计算机中占据一个字节,那么就是 8 bit,所以最大就是 2^7 = 1111 1111。

Java 中用补码来表示二进制数,补码的最高位是符号位,最高位用 0 表示正数,最高位 1 表示负数,正数的补码就是其本身,由于最高位是符号位,所以正数表示的就是 0111 1111 ,也就是 127。最大负数就是 1111 1111,这其中会涉及到两个 0 ,一个 +0 ,一个 -0 ,+0 归为正数,也就是 0 ,-0 归为负数,也就是 -128,所以 byte 的范围就是 -128 - 127。

HashMap 和 HashTable 的区别

相同点

HashMap 和 HashTable 都是基于哈希表实现的,其内部每个元素都是 key-value 键值对,HashMap 和 HashTable 都实现了 Map、Cloneable、Serializable 接口。

不同点

  • 父类不同:HashMap 继承了 AbstractMap 类,而 HashTable 继承了 Dictionary

  • 空值不同:HashMap 允许空的 key 和 value 值,HashTable 不允许空的 key 和 value 值。HashMap 会把 Null key 当做普通的 key 对待。不允许 null key 重复。

  • 线程安全性:HashMap 不是线程安全的,如果多个外部操作同时修改 HashMap 的数据结构比如 add 或者是 delete,必须进行同步操作,仅仅对 key 或者 value 的修改不是改变数据结构的操作。可以选择构造线程安全的 Map 比如 Collections.synchronizedMap 或者是 ConcurrentHashMap。而 HashTable 本身就是线程安全的容器。
  • 性能方面:虽然 HashMap 和 HashTable 都是基于单链表的,但是 HashMap 进行 put 或者 get

    3w 字长文爆肝 Java 基础面试题!太顶了!!!的更多相关文章

    1. 一份最贴近真实面试的Java基础面试题

      这是一份Java基础知识的面试题.在网上的关于Java的面试题数不胜数,但认真看过感觉大多数都没有实用性,有很多是面试官根本就不会问到的,那些已经脱离了实际开发的技术问题.而这份资料来源自一份个人觉得 ...

    2. 经典的Java基础面试题集锦

      经典的Java基础面试题集锦,欢迎收藏和分享. 问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示”main方法不是public的”. 问题:Java里的传引用 ...

    3. 非常全面的java基础笔试题

      下面是java基础笔试题,当时我去笔试,做了1个小时(80道选择题,后面的简答题就没时间做了),结果很吓人,太挫了,最后被面试官忽悠去培训去了,呵呵.我偷偷把面试题弄了下来,用来学习吧,也希望能对你们 ...

    4. Java基础机试题

      package day8;import java.util.Scanner;/** * Java基础机试题 * @author:lyrand * */public class convert {   ...

    5. 100道Java基础面试题收集整理(附答案)

      不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...

    6. 大数据学习--day04(选择结构、循环结构、大数据java基础面试题)

      选择结构.循环结构.大数据java基础面试题 switch: 注意: byte short int char String(jdk1.7支持) 不能是 long float double boolea ...

    7. 最新28道java基础面试题-上

      28道java基础面试题 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪 ...

    8. 28道java基础面试题-下

      28道java基础面试题下 15.Java语言如何进行异常处理,关键字:throws.throw.try.catch.finally分别如何使用? 答:Java通过面向对象的方法进行异常处理,把各种不 ...

    9. Java基础面试题集(一)

      Java基础面试题 一.面向对象编程(OOP) 7 二.常见的Java问题 7 2.1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? 7 2.2.JDK和JRE的区别是什么? ...

    10. 2w字长文!手撸一套 Java 基础面试题

      Java 基础篇 Java 有哪些特点 并发性的: 你可以在其中执行许多语句,而不必一次执行它 面向对象的:基于类和面向对象的编程语言. 独立性的: 支持一次编写,到处运行的独立编程语言,即编译后的代 ...

    随机推荐

    1. Java并发编程:volatile 关键字

      转自:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 其实Java语言是支持多线程的,为了解决线程并发的问题,在语言内部 ...

    2. win7 点IE浏览器无法打开

      现象:win7系统 打开未响应, 装其他浏览器可以使用,但很慢,且有密码框输入不了 处理: WIN7删除添加程序中,选打开或关闭windows功能,其中就有IE11的勾选了, 然后清除勾选,即会出现提 ...

    3. [C#] C# 知识回顾 - Lambda

      C# 知识回顾 - Lambda 序 它是第十一个希腊字母,一个拥有失意.无奈.孤独.低调等含义的流行符号,也指示一款称为“半条命”的游戏. 不过,这次我所讲的是 C# 中的 Lambda. 目录 L ...

    4. JHipster生成微服务架构的应用栈(二)- 认证微服务示例

      本系列文章演示如何用JHipster生成一个微服务架构风格的应用栈. 环境需求:安装好JHipster开发环境的CentOS 7.4(参考这里) 应用栈名称:appstack 认证微服务: uaa 业 ...

    5. C++:STL vector:sizeof(vector)

      原文地址:http://blog.csdn.net/zcsylj/article/details/7857009 int的大小是4,定义vector<int> vec,vec中有一个元素, ...

    6. hdu4870 高斯消元

      题意 一个人打比赛 ,rating 有p的概率 为加50分 有1-p的概率为 x-100分 最大值为 1000 最小值为0 有两个号 每次拿较小的号来提交 , 计算最后到达 1000分得期望场数是多少 ...

    7. Codeforces Round #546 (Div. 2) E - Nastya Hasn&#39;t Written a Legend

      这题是一个贼搞人的线段树 线段树维护的是 区间和a[i - j] 首先对于update的位置可以二分查找 其次update时候的lazy比较技巧 比如更新的是 l-r段,增加的是c 那么这段的值为: ...

    8. LoadRunner FAQ2

      LR中参数的定义和赋值 1.参数的赋值和取值 lr_save_string("hello world","param"); lr_eval_string(&qu ...

    9. python学习之老男孩python全栈第九期_day022知识点总结——初识面向对象

      一. 面向对象的引入# 人狗大战 def person(name,HP,aggr,sex): person = { 'name':name, # 昵称 'HP':HP, # 生命值 'aggr':ag ...

    10. easyui datagrid如何获取到每行的文本框

      在return '<input type="text" name="txtCount" class="inputvalue"/> ...