2023最新面试题-Java-2

基础语法

1. Java有哪些数据类型

定义 Java 语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同 大小的内存空间。   细化的数据类型就是占用空间的基本元素。
分类
基本数据类型
  • 数值型
    整数类型 (byte,short,int,long)
    浮点类型 (float,double)
  • 字符型(char)
  • 布尔型(boolean)
引用数据类型
  • (class)   eg:String
  • 接口(interface)
  • 数组([])

 1-24-8-4-2-1 空间大小对称记忆

2. switch 是否能作用在 byte 上,是否能作用在 long 上,是否 能作用在 String

Java 5 以前, switch(expr) 中, expr 只能是 byte short char int 。从 Java5 开始, Java 中引入 了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始, expr 还可以是字符串( String ),但是长整 型(long )在目前所有的版 本中都是不可以的。

3. 用最有效率的方法计算 2 乘以 8

2 << 3 (左移 3 位相当于乘以 2 3 次方,右移 3 位相当于除以 2 3 次 方)。
    public static void main(String[] args) {
        System.out.println(2<<3);
    }

 

4. Math.round(11.5) 等于多少?Math.round(-11.5) 等于多少

Math.round(11.5) 的返回值是 12 Math.round(-11.5) 的返回值是 -11 。四舍 五入的原理是在参数上加 0.5 然后进行下取整。 四舍五入 >0.5统一加0.几, <0.5 统一减0.几。

5. float f=3.4;是否正确

不正确。 3.4 是双精度数,将双精度型( double )赋值给浮点型( float )属于 下转型( down-casting , 也称为窄化)会造成精度损失,因此需要强制类型转 换float f =(float)3.4; 或者写成 float f =3.4F;

6. short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗

涉及Java的强制类型转换  支持向上自动转型

对于 short s1 = 1; s1 = s1 + 1; 由于 1 int 类型,因此 s1+1 运算结果也是 int 型,需要强制转换类型才 能赋值给 short 型。 而 short s1 = 1; s1 += 1; 可以正确编译,因为 s1+= 1; 相当于 s1 = (short(s1 + 1); 其 中有隐含的强制类型转换。

7.注释

定义:用于解释说明程序的文字
分类
单行注释 格式: // 注释文字
多行注释 格式: /* 注释文字 */
文档注释 格式: /** 注释文字 */

8. 访问修饰符 public,private,protected,以及不写(默认)时的 区别

定义 Java 中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访 问。 Java 支持 4 种不同的
访问权限。
分类
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部 类)
default ( 即缺省,什么也不写,不使用任何关键字) : 在同一包内可见,不使用 任何修饰符。使用
对象:类、接口、变量、方法。
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意: 不能修饰类(外部
类)。
public : 对所有类可见。使用对象:类、接口、变量、方法

9. final 有什么用?

用于修饰类、属性和方法;
  • final修饰的类不可以被继承
  • final修饰的方法不可以被重写
  • final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引
  • 用指向的内容是可以改变的

10. final finally finalize区别

1. final 可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修
饰变量表示该变量是一个常量不能被重新赋值。
2. finally 一般作用在 try-catch 代码块中,在处理异常的时候,通常我们将一定要执行的代码方法
finally 代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代
码。
3. finalize 是一个方法,属于 Object 类的一个方法,而 Object 类是所有类的父类,该方法一般由垃圾
回收器来调用,当我们调用 System.gc() 方法的时候,由垃圾回收器调用 finalize() ,回收垃圾,一
个对象是否可回收的最后判断。

11. thissuper的区别

  • super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函 数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
  • this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的 形参与类中的成员数据同名,这时需用this来指明成员变量名)
  • super()this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其 它构造方法。
  • super()this()均需放在构造方法内第一行。
  • 尽管可以用this调用一个构造器,但却不能调用两个。
  • thissuper不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造 函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意 义,编译器也不会通过。
  • this()super()都指的是对象,所以,均不可以在static环境中使用。包括:
  • static变量,static方法,static语句块。
  • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。

12. static存在的主要意义

static 的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属 性和调用方法!
static 关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。 static 块可以置于类中 的任何地方,类中可以有多个static 块。在类初次被加载的时候,会按照 static 块的顺序来执行每个 static 块,并且只会执行一次。为什么说static 块可以用来优化程序性能,是因为它的特性 : 只会在类加载的时 候 执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static 代码块中进行。

因此比较常见的static应用场景有:

1 、修饰成员变量
2 、修饰成员方法
3 、静态代码块
4 、修饰类【只能修饰内部类也就是静态内部类】
5 、静态导包

static注意事项

1 、静态只能访问静态。 2 、非静态既可以访问非静态的,也可以访问静态的。

13. 抽象类和接口的对比

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。
从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。

相同点

  • 接口和抽象类都不能实例化
  • 都位于继承的顶端,用于被其他实现或继承
  • 都包含抽象方法,其子类都必须覆写这些抽象方法

 不同点

抽象类
接口
声明
抽象类使用 abstract 关键字声明
接口使用 interface 关键字声明
实现
子类使用 extends 关键字来继承抽象类。如果子类
不是抽象类的话,它需要提供抽象类中所有声明
的方法的实现
子类使用 implements 关键字来实现
接口。它需要提供接口中所有声明的
方法的实现
抽象类可以有构造器
接口不能有构造器
访
抽象类中的方法可以是任意访问修饰符
接口方法默认修饰符是 public 。并且
不允许定义为 private 或者
protected
一个类最多只能继承一个抽象类
一个类可以实现多个接口
抽象类的字段声明可以是任意的
接口的字段默认都是 static final
备注 Java8 中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间 的差异。

14. 抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承, 这样彼此就会产生矛
盾,所以 final 不能修饰抽象类

15. 创建一个对象用什么关键字?对象实例与对象引用有何不同?

new 关键字, new 创建对象实例(对象实例在堆内存中),对象引用指向对象实 例(对象引用存放在栈 内存中)。一个对象引用可以指向0 个或 1 个对象(一根 绳子可以不系气球,也可以系一个气球) ; 一个 对象可以有n 个引用指向它(可以 用 n 条绳子系住一个气球)
没有对象引用,丢失跟可达性就代表是可以回收的对象。

变量与方法

16. 成员变量与局部变量的区别有哪些

 变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上 讲,变量其实是内存中的 一小块区域

成员变量:方法外部,类内部定义的变量

局部变量:类的方法中的变量。 成员变量和局部 变量的区别。

作用域

成员变量:针对整个类有效。
局部变量:只在某个范围内有效。 ( 一般指的就是方法 , 语句体内 )

存储位置

成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结 束后,就自动释放。

 生命周期

成员变量:随着对象的创建而存在,随着对象的消失而消失。
局部变量:当方法调用完,或者语句结束后,就自动释放。

初始值

成员变量:有默认初始值。
局部变量:没有默认初始值,使用前必须赋值。

使用原则

在使用变量时需要遵循的原则为:就近原则 首先在局部范围找,有就使用;接着在成员位置找。

17. 静态变量和实例变量区别

静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会 有一份,在类的加载过程 中,JVM 只为静态变量分配一次内存空间。
实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量 是属于实例对象的,在内 存中,创建几次对象,就有几份成员变量。

18 静态方法和实例方法有何不同?

静态方法和实例方法的区别主要体现在两个方面:
1. 在外部调用静态方法时,可以使用 " 类名 . 方法名 " 的方式,也可以使 用 " 对象名 . 方法名 " 的方式。而 实例方法只有后面这种方式。也就是说,调 用静态方法可以无需创建对象。
2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量 和静态方法),而不允许访 问实例成员变量和实例方法;实例方法则无此 限制

19. 内部类的分类有哪些

内部类可以分为四种: 成员内部类、局部内部类、匿名内部类和静态内部类。

静态内部类

定义在类内部的静态类,就是静态内部类。
1 public class Outer {
2
3 private static int radius = 1;
4
5 static class StaticInner {
6 public void visit() {
7 System.out.println("visit outer static variable:" + radius);
8 }
9 }
10 }
静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量; 静态内部类的创建方 式,new 外部类 . 静态内部类 () ,如下:
1 Outer.StaticInner inner = new Outer.StaticInner();
2 inner.visit

成员内部类

 定义在类内部,成员位置上的非静态类,就是成员内部类。

1 public class Outer {
2
3 private static int radius = 1;
4 private int count =2;
5
6 class Inner {
7 public void visit() {
8 System.out.println("visit outer static variable:" + radius);
9 System.out.println("visit outer variable:" + count);
10 }
11 }
12 }
成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公 有。成员内部类依赖于外 部类的实例,它的创建方式外部类实例.new 内部类 () ,如 下:
1 Outer outer = new Outer();
2 Outer.Inner inner = outer.new Inner();
3 inner.visit();

局部内部类

 定义在方法中的内部类,就是局部内部类

1 public class Outer {
2
3 private int out_a = 1;
4 private static int STATIC_b = 2;
5
6 public void testFunctionClass(){
7 int inner_c =3;
8 class Inner {
9 private void fun(){
10 System.out.println(out_a);
11 System.out.println(STATIC_b);
12 System.out.println(inner_c);
13 }
14 }
15 Inner inner = new Inner();
16 inner.fun();
17 }
18 public static void testStaticFunctionClass(){
19 int d =3;
20 class Inner {
21 private void fun(){
22 // System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外
部类的实例变量
23 System.out.println(STATIC_b);
24 System.out.println(d);
25 }
26 }
27 Inner inner = new Inner();
28 inner.fun();
29 }
30 }
定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法 中的局部类只能访问外 部类的静态变量和方法。局部内部类的创建方式,在对应 方法内,new 内部类 () ,如下:

1 public static void testStaticFunctionClass(){
2 class Inner {
3 }
4 Inner inner = new Inner();
5 }

匿名内部类

 匿名内部类就是没有名字的内部类,日常开发中使用的比较多。

1 public class Outer {
2
3 private void test(final int i) {
4 new Service() {
5 public void method() {
6 for (int j = 0; j < i; j++) {
7 System.out.println("匿名内部类" );
8 }
9 }
10 }.method();
11 }
12 }
13 //匿名内部类必须继承或实现一个已有的接口
14 interface Service{
15 void method();
16 }
除了没有名字,匿名内部类还有以下特点:
  • 匿名内部类必须继承一个抽象类或者实现一个接口。
  • 匿名内部类不能定义任何静态成员和静态方法。
  • 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final
  • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方 法。

匿名内部类创建方式: 

1 new 类/接口{
2 //匿名内部类实现部分
3 }
内部类的优点
  • 我们为什么要使用内部类呢?因为它有以下优点:
  • 一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
  • 内部类不为同一包的其他类所见,具有很好的封装性;
  • 内部类有效实现了多重继承,优化 java 单继承的缺陷。
  • 匿名内部类可以很方便的定义回调。

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

方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态 性,而后者实现的是运行 时的多态性。
重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不 同、顺序不同),与方法 返回值和访问修饰符无关,即重载的方法不能根据返回 类型进行区分
重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛 出的异常小于等于父 类,访问修饰符大于等于父类(里氏代换原则);如果父类 方法访问修饰符为private 则子类中就不是重 写。

21. == equals 的区别是什么

 == : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同 一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况: 情况 1 :类没有覆盖
equals() 方法。则通过 equals() 比较该类的两个对象时, 等价于通过 “==” 比较这两个对象。
情况 2 :类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象 的内容相等;若它们的内 容相等,则返回 true ( 即,认为这两个对象相等 )
举个例子:
1 public class test1 {
2 public static void main(String[] args) {
3 String a = new String("ab"); // a 为一个引用
4 String b = new String("ab"); // b为另一个引用,对象的内容一样
5 String aa = "ab"; // 放在常量池中
6 String bb = "ab"; // 从常量池中查找
7 if (aa == bb) // true
8 System.out.println("aa==bb");
9 if (a == b) // false,非同一对象
10 System.out.println("a==b");
11 if (a.equals(b)) // true
12 System.out.println("aEQb");
13 if (42 == 42.0) { // true
14 System.out.println("true");
15 }
16 }
17 }
说明:
  • String中的equals方法是被重写过的,因为objectequals方法是比较的对象的 内存地址,而 Stringequals方法比较的是对象的值。
  • 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要 创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建 一个String对象。

22. hashCode equals (重要)

 HashSet如何检查重复

两个对象的 hashCode() 相同,则 equals() 也一定为 true ,对吗?
hashCode equals 方法的关系
面试官可能会问你: 你重写过 hashcode equals 么,为什么重写 equals 时 必须重写 hashCode 方 法?
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整 数。这个哈希码的作用是 确定该对象在哈希表中的索引位置。hashCode() 定义 在 JDK Object.java 中,这就意味着 Java 中的任何 类都包含有hashCode() 函数。
散列表存储的是键值对 (key-value) ,它的特点是:能根据 快速的检索出 对应的 。这其中就利用 到了散列码!(可以快速找到所需要的对象)

为什么要有 hashCode

 我们以“HashSet 如何检查重复为例子来说明为什么要有 hashCode

 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对 象加入的位置,同时也 会与其他已经加入的对象的 hashcode 值作比较,如果 没有相符的hashcodeHashSet会假设对象没 有重复出现。但是如果发现有相 同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相 等的对 象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不 同的话,就会重 新散列到其他位置。。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速 度。

对象的相等与指向他们的引用相等,两者有什么不同?

  • 对象的相等 比的是内存中存放的内容是否相等。
  • 引用相等 比较的是他们指向的 内存地址是否相等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值