乐趣区

面试题系列Java基础

本文次要包含 Java 根底及面向对象相干面试题。

1,Java 科普 1.1 为什么安装包要分 JDK 和 JRE?1.2 为什么 Java 语言是跨平台的?1.3 为什么装置完 JDK 后要设置环境变量?1.4 Java 和 C ++ 区别 2,数据类型 & 变量 2.1 boolean 占几个字节?2.2 为什么 long 能够主动转换为 float?2.3 包装类型和根本数据类型的区别 2.4 String,StringBuffer,StringBuilder 的区别 2.5 String s = “Hello”;s = s + “world!”; 这两行代码执行后,原始的 String 对象中的内容到底变了没有?2.6 String str =“i”;和 String str = new String(“i”); 有区别吗?2.7 如何将字符串反转?2.8 Java 有几种变量?2.9 援用数据类型蕴含哪几种?3,运算符 3.1 == 和 equals 的区别 3.2 & 和 && 区别(| 和 || 同理)4,面向对象 4.1 什么是面向对象?4.2 封装相干 4.3 继承相干 4.4 多态相干 4.5 关键词 static4.6 关键词 final4.7 接口和抽象类的区别?4.8 为什么重写 equals 必须重写 hashCode?

1,Java 科普

1.1 为什么安装包要分 JDK 和 JRE?

JRE 次要蕴含 JVM,用于运行 Java 程序。
JDK 蕴含了 JRE,除此之外,蕴含了比方像 javac 等程序开发须要用到的工具。

先来说说什么是 JDK,JRE。

JDK:Java Development Kit Java 开发工具包【开发 Java 程序用】

JRE:Java Runtiome Environment Java 运行环境【运行 Java 程序用】

【注:下载的 JDK 包是蕴含了 JDK 和 JRE 的,JDK 和 JRE 是逻辑上的辨别,两者在 JDK 下载的包中都有】

JDK 与 JRE 的关系:以 Java 代码运行为例,编写好 Java 代码之后,通过 javac 将 java 源文件编译成 class 字节码文件, 而后通过 java 命令,运行字节码文件。那么运行字节码的环境就是 JRE。(JRE 的外围就是 JVM)

理解完 JDK 和 JRE 是什么之后,再聊聊为什么开发者过后要把一个安装包分成两局部呢?

平时应用的软件都是一键装置的,但 JDK 须要装置两次。JDK 的发明者不会这么无聊,成心给开发者减少麻烦。

【我想】:这应该跟生产环境的部署问题无关,对于生产环境部署 JDK 还是 JRE 始终饱受争议,具体情况依据我的项目而定。

出于对性能的思考,尽可能的使服务器轻,能少装一个软件就少装一个,这样生产环境部署 JRE 就 OK 了。【又省了资源】

除了这个方面之外,还有一种可能。JDK 的开发也有可能是分团队的,JDK 和 JRE 可能是交由不同团队开发,JDK 和 JRE 的耦合也可能因而而减小,从而放慢 JDK 的迭代版本。(毕竟当初 JDK 一年更新两次)

1.2 为什么 Java 语言是跨平台的?

JVM 有两个性能
– 将 class 字节码转换为机器码
– 兼容不同的操作系统

跨平台和 Java 虚拟机无关。

JVM 有两个次要的性能:

  • 适配不同的操作系统的指令集(兼容不同的操作系统)
  • 翻译字节码文件为机器码执行

(Oracle 官网上下载 JDK,不同操作系统的 JDK 是不一样的,对应不同的虚拟机)

1.3 为什么装置完 JDK 后要设置环境变量?

在解决这个问题之前,先来理解一些环境变量是干嘛的:

环境变量是在操作系统中一个具备特定名字的对象,它蕴含了一个或者多个应用程序所将应用到的信息。例如 Windows 和 DOS 操作系统中的 path 环境变量,当要求零碎运行一个程序而没有通知它程序所在的残缺门路时,零碎除了在当前目录上面寻找此程序外,还应到 path 中指定的门路去找。用户通过设置环境变量,来更好的运行过程。

简略来说,运行一个程序(命令),操作系统会从当前目录寻找,或者从环境变量中寻找。

换句话说,如果在 java,javac 的目录下执行这个两个命令,是没有问题的。然而如果更换了目录,零碎在当前目录找不到,就会去环境变量中寻找。所以 设置环境变量的基本目标是在电脑的任何一个文件夹下都能够编译运行 Java 程序。

1.4 Java 和 C ++ 区别

题外话,Java 和 C ++ 有什么区别?(据说有些面试官老爱干这种事)

  • C++ 反对多继承,Java 反对单继承
  • Java 有垃圾回收机制
  • Java 不反对指针,更加平安

2,数据类型 & 变量

2.1 boolean 占几个字节?

示意变量:4 个字节(转换为 int 存储)
示意 byte 数组:1 个字节

2.2 为什么 long 能够主动转换为 float?

float,double 采纳指数形式存储,能示意的数比 long 更大

System.out.println(Long.MAX_VALUE);
System.out.println(Float.MAX_VALUE);
System.out.println(Double.MAX_VALUE);
System.out.println(Float.MAX_VALUE>Long.MAX_VALUE);


9223372036854775807
3.4028235E38
1.7976931348623157E308
true

float 和 double 应用指数示意,取值范畴在

-3.4*10^38 – 3.4*10^38

顺便看看 float 和 double 的精度:7 位和 16 位。

2.3 包装类型和根本数据类型的区别

初始值:包装类型的初始值为 null,根本数据类型的初始值基本上是 0,char 是 ’u000′
存储形式:包装类型存在堆里,根本数据类型存在栈中

2.4 String,StringBuffer,StringBuilder 的区别

– 可变性
String 底层应用 fina 润饰的数组实现,是不可变的,StringBuffer 和 StringBuilder 是可变的
– 安全性
String 不可变,天然线程平安,StringBuffer 应用 synchronized 同步锁实现线程平安,StringBuilder 是线程不平安的

  • 可变性

    String 是不可变的,StringBuffer 和 StringBuilder 是可变的

    String string1 = “111”;
    string1 = “222”;
    System.out.println(string1);

    string1 指向 222 时,创立了一个新的对象并指向它

    String 底层应用 final 润饰的数组实现,故是不变的

    public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

    private final char value[];

  • 安全性

    StringBuffer 和 String 是线程平安的,,StringBuilder 是线程不平安的。

    String 中的对象是不可变的,也就能够了解为常量,线程平安。

    StringBuffer 对办法加了 synchronized 同步锁所以是线程平安的。

  • 对于三者应用的总结

    1. 操作大量的数据: 实用 String
    2. 单线程操作字符串缓冲区下操作大量数据: 实用 StringBuilder
    3. 多线程操作字符串缓冲区下操作大量数据: 实用 StringBuffer

2.5 String s = “Hello”;s = s + “world!”; 这两行代码执行后,原始的 String 对象中的内容到底变了没有?

没有,只是指向了另外一个对象。

因为 String 被设计成不可变 (immutable) 类(final 润饰),所以它的所有对象都是不可变对象。

在这段代码中,s 原先指向一个 String 对象,内容是 “Hello”,而后对 s 进行了 + 操作

这时,s 不指向原来那个对象了,而指向了另一个 String 对象,内容为 ”Hello world!”

原来那个对象还存在于内存之中,只是 s 这个援用变量不再指向它了。

2.6 String str =“i”;和 String str = new String(“i”); 有区别吗?

前者会被 JVM 调配到常量池中,常量池中没有反复的元素,如果再次创立一个字符串变量等于 i 的话,就会间接指向常量池中的 i。

后者是 new 了一个对象,堆中是容许对象反复的。

前者会被 JVM 调配到常量池中,常量池中没有反复的元素。

String str1 =“i”;
String str2 =“i”;

str2 不会从新创立一个常量,而是指向 str1。

String str1 = new String(“i”);
String str2 = new String(“i”);

str1 会在堆内存中创建对象

str2 还是会再次创立一个新的对象

2.7 如何将字符串反转?

应用 StringBuilder 或者 StringBuffer 的 reverse()办法。

StringBuffer str1 = new StringBuffer(“12345”);
StringBuffer str2 = str1.reverse();
System.out.println(str2);

54321

2.8 Java 有几种变量?

  • 类变量

    独立于办法之外,必须用 static 润饰

  • 实例变量

    独立于办法之外,不必 static 润饰

  • 局部变量

    办法中的变量

2.9 援用数据类型蕴含哪几种?

  • 接口
  • 数组

3,运算符

3.1 == 和 equals 的区别

equals 用于比拟内容是否雷同(源自 Object 类,通常被重写)

== 对于根本数据类型比拟值雷同,对于援用数据类型比拟内存地址是否雷同(是否是同一个对象)

知乎上十分形象的一张图:

3.2 & 和 && 区别(| 和 || 同理)

& : 两边都为 true 时才为 true

|:两边有一个为 false 即为 false

短路逻辑运算符

&&:右边为 fasle 间接返回 flase(不计算左边)

||:右边为 true 间接返回 true(不计算左边)

就是为了简化计算量

^ 示意异或,雷同为 false,不同为 true

4,面向对象

4.1 什么是面向对象?

如果摒弃软件开发的领域,这是一种通过明确社会分工而提高效率的办法。

在软件开发的范畴内,就是通过形象出零碎性能而实现最大化代码复用的开发模式。

4.2 封装相干

  • 什么是封装

    通过暗藏实现,裸露接口,一来实现代码解耦,二来通过拜访修饰符保障数据安全。

4.3 继承相干

  • 继承的作用?

    实现代码复用

  • 继承的规定?

    • 子类继承父类非 private 的属性和办法
    • 子类能够扩大本人的属性和办法
  • 结构器是否会被继承?

    • 结构器不会被继承,但子类对象初始化时会调用父类无参结构器

      【为什么。子类和父类有最根本的依赖关系,比如说数据依赖】

    • 当父类显式写了有参结构器,且没有无参结构器。子类继承父类的时候必须 显式的调用父类的有参结构器。调用的形式能够应用 super(a,b)来调用。
  • 子类父类的初始化程序

    准则:动态优于非动态,父类优于子类

    – 父类动态变量,动态语句块
    – 子类动态变量,动态语句块

    – 父类非动态代码块,结构器
    – 子类非动态代码块,结构器

4.4 多态相干

  • 什么是多态?

    一类事物的多种体现状态。(比方手机有各种各样的品牌,但都属于手机这一类事物)

  • 如何体现多态?

    办法重载:针对本类的不同办法而言,办法名雷同,参数不同(个数,程序)【返回类型随便】

    办法重写:针对继承而言,除了办法体能够自定义外,其余必须与父类保持一致(办法名,返回类型,参数)

  • 向上转型 & 向下转型

    up:子类转换为父类,目标是拜访父类的公共办法,实现代码的复用和简洁(比方 100 个类把公共办法写在父类中,就不须要每个类都写一遍了)

    down:父类转换为子类,据说是为了调用子类的扩大办法。(为啥不间接 new 一个对象,已提交知乎问答)

4.5 关键词 static

  • 润饰变量

    称为动态变量,类变量,全局变量

    可间接通过类名. 变量名拜访

  • 润饰办法

    称为静态方法,类办法

    可通过类名. 办法名间接拜访

    • 非 static 办法能够拜访 static 办法,static 办法不能拜访非 static 办法

4.6 关键词 final

  • 润饰类不能被继承
  • 润饰办法不能被重写
  • 润饰变量则变量变为常量

4.7 接口和抽象类的区别?

  • 继承与实现

    类只能单继承,但能够实现多接口

  • 办法是否能实现

    抽象类不仅能够做办法申明,也能够做办法实现。(接口只能做办法申明)

  • 修饰符

    接口的变量都默认采纳 final 润饰,办法采纳 public 润饰。

    抽象类可自定义。

4.8 为什么重写 equals 必须重写 hashCode?

equals 和 hashCode 位于 Object 类中,所有的类都会继承 Object 类。

equals 通常被用来比拟对象的内容是否雷同,hashCode 是用来返回对象 Hash 值的一种办法。

如果不重写 hashCode 会导致,equals 雷同但 hashCode 不雷同,equals 不雷同但 hashCode 雷同。

重写的目标一来为了防止 hash 抵触,二来进步对象访问速度。

退出移动版