java有指针吗 面试_Java基础常见面试题一

从设计层面上看,抽象类提供了一种 IS-A 关系(父子关系),那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象,子类会继承父类所有的属性和方法。而接口更像是一种 LIKE-A 关系(师徒关系),它只是提供一种方法实现契约,需要实现什么样的功能就实现什么样的接口。

从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。

接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。

接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。

在 jdk8 以前,接口中的方法默认全是抽象方法,不能有方法体,而 抽象类中可以有不声明为抽象方法的方法,这些方法可以有方法体。但是jdk 8以后,接口也支持有方法体的默认方法了。

接口的体量相对都比较小,而类的体量相对就比较大,体量大的话会增大维护成本和降低使用效率

使用选择

使用接口的场景:

需要让不相关的类都实现一个方法,增加某个功能时。例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法;

需要使用多重继承。

使用抽象类的场景:

需要在几个相关的类中共享代码。

需要能控制继承来的成员的访问权限,而不是都为 public。

需要继承非静态和非常量字段。

在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低

24、 基础数据类型和包装类对象,需要使用包装类的场景

有了基本类型为什么还要有包装类型呢?

我们知道Java是一个面相对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型Collection时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

另外,当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装器类了。

基本类型与包装类型的异同:

1、在Java中,一切皆对象,但八大基本类型却不是对象。

2、声明方式的不同,基本类型无需通过new关键字来创建,而封装类型则需new关键字。

3、存储方式及位置的不同,基本类型是直接存储变量的值,保存在堆栈中能高效的存取;封装类型需要通过引用指向实例,具体的实例保存在堆中;

4、初始值的不同,封装类型的初始值为null,基本类型的的初始值视具体的类型而定,比如int类型的初始值为0,boolean类型为false;

5、使用场景的不同,包装类的使用场景更加多样。比如与集合类合作使用时只能使用包装类型。

6、什么时候该用包装类,什么时候该用基本类型,看基本的业务来定:这个字段允不允许null值,如果允许,则必然要用封装类;否则,基本类型就可以了。如果用到比如泛型和反射调用函数,就需要用包装类!

包装类的使用场景:

集合类中只能使用包装类

泛型中使用包装类

反射调用函数中使用包装类

数据库查询的结果为null时,不能赋值给基本类型,应该使用包装类

25、在一个静态方法内调用一个非静态成员为什么是非法的?

因为非静态成员只有存在于一个对象中才有意义,但是由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态成员方法。

26、 在 Java 中定义一个不做事且没有参数的构造方法的作用

为了子类对象能够正确的初始化。在执行子类的构造方法之前,如果没有显示的调用 super()函数来指定所调用的父类特定的构造方法,则会默认调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

27、构造方法作用和有哪些特性?

作用是完成对类实例对象的初始化工作

特性:

名字与类名相同。

没有返回值,但不能用 void 声明构造函数。

生成类的实例

对象时自动执行,无需调用。

28、静态方法和实例方法有何不同

静态方法属于类,而实例方法属于对象,实例方法只能通过对象调用,而静态方法还可以通过类名.静态方法来使用

静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。

29、final 关键字的作用

final 关键字主要用在三个地方:变量、方法、类。

1. 变量

声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。

对于基本类型,final 使数值不变;

对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的。

2. 方法

声明方法不能被子类重写。

private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。

3. 类

声明类不允许被继承。

30、异常体系

1. 所有异常继承公共祖先【throwable类】

2. 异常分为两大类 : Exception & Error

(1) Error 是【程序无法处理】的错误,大部分是代码在JVM运行时出现问题。代码逻辑错误或者外部环境错误

如 程序申请内存时,内存资源不足。抛出OOM

Error发生时,JVM一般会【终止】线程

(2) Exception是【程序可以处理】的错误

常见Exception:

ArithmeticException 算数异常

NullPointException 空指针异常

ArrayIndexOutOfBoundsException 下标越界

31、内存泄漏

程序没有释放已经不再使用的内存,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,因此这段内存一直被占用,无法释放,造成空间的浪费。

长生命周期的引用指向了短生命周期的对象

内存泄漏案例

1. 单例模式

Instance可能早已不被使用,

但是类仍持有Instance的【引用】。

因此Intance【生命周期】和引用相同,造成内存泄漏。

2. 容器

容器内的【键值对】不被使用时,

Map仍持有key对象& value对象的【引用】,

则会造成内存泄漏。

怎么查内存泄漏

《Java线上内存溢出问题排查步骤》

32、内存溢出

要求分配的内存超过了系统能给我的,系统不能满足需求。内存泄漏的堆积如果不及时处理最终会导致内存溢出

33、Java 中 IO 流分为几种?

按照流的流向分,可以分为输入流和输出流;

按照操作单元划分,可以划分为字节流和字符流;

34、既然有了字节流,为什么还要有字符流?

35、为什么 Java 不支持运算符重载? 另一个类似棘手的 Java 问题。为什么 C++ 支持运算符重载而 Java 不支持?

有人可能会说+运算符在 Java 中已被重载用于字符串连接,不要被这些论据所欺骗。 与 C++ 不同,Java 不支持运算符重载。Java 不能为程序员提供自由的标准算术运算符重载,例如+, - ,*和/等。如果你以前用过 C++,那么 Java 与 C++ 相比少了很多功能,例如 Java 不支持多重继承,Java 中没有指针,Java 中没有引用传递。另一个类似的问题是关于 Java 通过引用传递,这主要表现为 Java 是通过值还是引用传参。虽然我不知道背后的真正原因,但我认为以下说法有些道理,为什么 Java 不支持运算符重载。

(1)简单性和清晰性。

清晰性是 Java 设计者的目标之一。设计者不是只想复制语言,而是希望拥有一种清晰,真正面向对象的语言。添加运算符重载比没有它肯定会使设计更复杂,并且它可能导致更复杂的编译器, 或减慢 JVM,因为它需要做额外的工作来识别运算符的实际含义,并减少优化的机会, 以保证 Java 中运算符的行为。

(2)避免编程错误。

Java 不允许用户定义的运算符重载,因为如果允许程序员进行运算符重载,将为同一运算符赋予多种含义,这将使任何开发人员的学习曲线变得陡峭,事情变得更加混乱。据观察,当语言支持运算符重载时,编程错误会增加,从而增加了开发和交付时间。由于 Java 和 JVM 已经承担了大多数开发人员的责任,如在通过提供垃圾收集器进行内存管理时,因为这个功能增加污染代码的机会, 成为编程错误之源, 因此没有多大意义。

(3)JVM 复杂性。

从 JVM 的角度来看,支持运算符重载使问题变得更加困难。通过更直观,更干净的方式使用方法重载也能实现同样的事情,因此不支持 Java 中的运算符重载是有意义的。与相对简单的 JVM 相比,复杂的 JVM 可能导致 JVM 更慢,并为保证在 Java 中运算符行为的确定性从而减少了优化代码的机会。 4)让开发工具处理更容易。这是在 Java 中不支持运算符重载的另一个好处。省略运算符重载使语言更容易处理,这反过来又更容易开发处理语言的工具,例如 IDE 或重构工具。Java 中的重构工具远胜于 C++。

36、假设你有一个类,它序列化并存储在持久性中, 然后修改了该类以添加新字段。如果对已序列化的对象进行反序列化, 会发生什么情况

这取决于类是否具有其自己的 serialVersionUID。正如我们从上面的问题知道, 如果我们不提供 serialVersionUID, 则 Java 编译器将生成它, 通常它等于对象的哈希代码。通过添加任何新字段, 有可能为该类新版本生成的新 serialVersionUID 与已序列化的对象不同, 在这种情况下, Java 序列化 API 将引发 java.io.InvalidClassException, 因此建议在代码中拥有自己的 serialVersionUID, 并确保在单个类中始终保持不变。

37、Java 序列化机制中的兼容更改和不兼容更改是什么?

真正的挑战在于通过添加任何字段、方法或删除任何字段或方法来更改类结构, 方法是使用已序列化的对象。根据 Java 序列化规范, 添加任何字段或方法都面临兼容的更改和更改类层次结构或取消实现的可序列化接口, 有些接口在非兼容更改下。对于兼容和非兼容更改的完整列表, 我建议阅读 Java 序列化规范。 4.我们可以通过网络传输一个序列化的对象吗 是的 ,你可以通过网络传输序列化对象, 因为 Java 序列化对象仍以字节的形式保留, 字节可以通过网络发送。你还可以将序列化对象存储在磁盘或数据库中作为 Blob。  在 Java 序列化期间,哪些变量未序列化? 这个问题问得不同, 但目的还是一样的, Java 开发人员是否知道静态和瞬态变量的细节。由于静态变量属于类, 而不是对象, 因此它们不是对象状态的一部分, 因此在 Java 序列化过程中不会保存它们。由于 Java 序列化仅保留对象的状态,而不是对象本身。瞬态变量也不包含在 Java 序列化过程中, 并且不是对象的序列化状态的一部分。在提出这个问题之后,面试官会询问后续内容, 如果你不存储这些变量的值, 那么一旦对这些对象进行反序列化并重新创建这些变量, 这些变量的价值是多少?这是你们要考虑的。

38、Java 中,嵌套公共静态类与顶级类有什么不同?

类的内部可以有多个嵌套公共静态类,但是一个 Java 源文件只能有一个顶级公共类,并且顶级公共类的名称与源文件名称必须一致。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值