目录
7. private 、缺省、protected、public的表格化作用区域
8. main方法的public能不能换成private?为什么?
10. 构造器Constructor是否可被overload?
14. 父类哪些成员可以被继承,属性可以被继承吗?可以或者不可以,请举下例子。
17. 构造器Constructor是否可被override?
18. 为什么要有重载,我随便命名一个别的函数名不行吗?谈谈你是怎么理解的。
21. 多态new出来的对象跟不多态new出来的对象区别在哪?
27. 静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
28. 是否可以从一个static方法内部发出对非static方法的调用?
29. 被static修饰的成员(类、方法、成员变量)能否再使用private进行修饰?
34. 静态代码块,普通代码块,构造方法,从类加载开始的执行顺序?
36. 判断题:使用final修饰一个变量时,是引用不能改变,引用指向的对象可以改变?
38. final或static final 修饰成员变量,能不能进行++操作?
40. 为什么不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法?
42. 接口是否可继承接口?抽象类是否可实现implements)接口?抽象类是否可继承实现类(concrete class)?
1. 面向对象,面向过程的理解?
面向过程编程
- 定义:强调将程序视为一系列过程或函数的集合。程序由一系列操作组成,这些操作通过函数调用的方式组织起来。
- 特征:
- 以函数为中心,数据和功能分开。
- 通过过程(函数)来操作数据,数据通常是全局的。
- 易于实现简单的程序,但在复杂系统中可能导致代码难以维护。
- 优点:
- 理解和实现简单,适合小型项目。
- 性能相对较高,因为直接操作数据。
面向对象编程
- 定义:强调将程序视为一组对象的集合。每个对象封装了数据和操作这些数据的方法。
- 特征:
- 以对象为中心,数据和功能结合在一起。
- 支持封装、继承和多态等特性。
- 更易于建模现实世界的复杂问题,适合大型项目。
- 优点:
- 提高代码的重用性和可维护性。
- 使得程序的结构更清晰,便于团队协作。
总结
- 面向过程适合简单、线性的问题,面向对象则更适合复杂的系统和应用程序。在选择使用哪种范式时,考虑项目的规模和复杂性是很重要的。
2. Java 的引用类型有哪几种
类、数组、接口;枚举、注解、记录
3. 类和对象的区别
类(Class)
- 定义:类是一个蓝图或模板,用于创建对象。它定义了一组属性(数据)和方法(行为)。
- 特征:
- 类描述了一种数据类型,包括数据成员(属性)和函数成员(方法)。
- 类本身不占用内存,只有在创建对象时,内存才会被分配。
- 类可以被继承,支持多态和封装等特性。
- 示例:假设有一个类叫
Car
,它可能有属性如color
和model
,以及方法如drive()
和stop()
。
对象(Object)
- 定义:对象是类的一个实例。它是根据类的定义创建的具体实体,包含类中定义的属性和方法的实际值。
- 特征:
- 每个对象都有自己的状态和行为,可以独立于其他对象。
- 对象在内存中占用空间,并持有类中定义的数据。
- 可以通过对象调用类中定义的方法。
- 示例:如果
Car
是类,那么myCar
就是一个对象,它可能具有color
属性的值为red
,model
属性的值为2020
。
总结
- 类是一个抽象概念,定义了对象的结构和行为;而对象是类的具体实例,拥有实际的数据和状态。
4. 面向对象,你解释一下,项目中哪些地方用到面向对象?
1. 模型与数据结构
- 现实世界建模:面向对象编程使得开发者能够用类来表示现实世界中的实体(如用户、产品、订单等),通过对象来管理这些实体的状态和行为。
- 数据结构:可以创建自定义的数据结构,封装数据并提供操作这些数据的方法。
2. 封装
- 信息隐藏:通过访问控制(如public、private和protected),可以限制对对象内部状态的直接访问,只允许通过公共方法进行操作,增强安全性和可维护性。
3. 继承
- 代码重用:可以通过继承创建新的类,重用现有类的属性和方法,减少代码重复。例如,可以创建一个
Vehicle
基类,Car
和Truck
可以继承它,分享相同的基本功能。
4. 多态
- 接口与实现:通过多态,允许使用统一的接口来调用不同类型的对象,提高了灵活性和扩展性。例如,可以定义一个
draw()
方法在多个图形类(如Circle
、Square
)中实现,使用相同的方法名但实现不同的行为。
5. 模块化设计
- 组织代码:面向对象编程促进代码的模块化,使得项目结构更清晰。每个类都可以独立开发、测试和维护,有助于团队协作。
6. 设计模式
- 应用设计模式:许多设计模式(如单例模式、观察者模式、工厂模式等)都是基于面向对象的思想,提供了解决常见问题的通用方法。
7. 用户界面(UI)组件
- 组件化开发:在图形用户界面(GUI)开发中,UI元素(如按钮、窗口)通常被设计为对象,每个组件都有自己的属性和行为,便于管理和扩展。
8. 系统的扩展与维护
- 便于扩展:通过继承和接口,系统可以轻松扩展功能,而无需大幅修改现有代码。这在迭代开发和持续集成的环境中特别重要。
5. Java虚拟机中内存划分为哪些区域,详细介绍一下
1. 方法区(Method Area)
- 定义:存放类的结构信息,包括字段、方法、常量池、静态变量和类的元数据等。
- 特点:
- 是所有线程共享的区域。
- 当类被加载时,它的相关信息会被存储在方法区中。
- Java 8 之前,方法区也包括运行时常量池,Java 8 之后,这一部分被移到了元空间(Metaspace)。
2. 堆区(Heap)
- 定义:用于存储对象实例和数组,是JVM中最大的内存区域。
- 特点:
- 所有线程共享堆内存。
- 在堆中分配的对象会在运行时通过垃圾回收(GC)进行管理。
- 堆内存的大小可以通过启动参数进行调整(如
-Xms
和-Xmx
)。
3. 栈区(Stack)
- 定义:用于存储局部变量、方法调用和返回值等信息。每个线程都有自己的栈区。
- 特点:
- 存储方法的调用链(方法栈帧),每个方法调用都会在栈中创建一个新的帧。
- 当方法调用结束,栈帧会被销毁,局部变量也随之释放。
- 栈内存的大小可以通过启动参数进行调整(如
-Xss
)。
4. 本地方法栈(Native Method Stack)
- 定义:用于存放Native方法的调用信息,与Java方法栈类似,但主要用于管理Native(非Java)方法。
- 特点:
- 本地方法栈的大小可以通过启动参数进行调整。
5. 程序计数器(Program Counter Register)
- 定义:用于记录当前线程执行的字节码的行号指示器。
- 特点:
- 每个线程都有自己的程序计数器,线程间不共享。
- 当线程执行方法时,程序计数器指向当前执行的字节码行号,当方法调用或返回时,程序计数器会相应更新。
6. 运行时常量池(Runtime Constant Pool)
- 定义:方法区的一部分,用于存放类中常量(如字符串字面量、数字等)。
- 特点:
- 在类加载时,常量池中的内容会被初始化。
- 可以动态添加常量,如字符串常量在运行时可以通过
String.intern()
方法添加。
总结
这些内存区域共同支持了Java程序的执行,合理地管理和使用这些内存区域对于提高程序性能和稳定性至关重要。通过理解JVM的内存结构,可以更好地进行性能调优和内存管理。
6. 对象存在Java内存的哪块区域里面?
在Java中,对象主要存在于堆区(Heap)。堆区是JVM中用于存储对象实例和数组的内存区域,是所有线程共享的。以下是关于堆区的进一步说明:
堆区的特点
- 动态分配:对象在运行时动态分配内存,使用
new
关键字创建时,JVM会在堆区分配足够的内存空间来存储对象。 - 垃圾回收:堆区中的对象由垃圾回收(Garbage Collection, GC)管理。当没有任何引用指向某个对象时,该对象会被标记为可回收,最终会被GC释放内存。
- 共享性:堆区的内存是所有线程共享的,多个线程可以同时访问堆中的对象。
7. private 、缺省、protected、public的表格化作用区域
修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
---|---|---|---|---|
private | √ | × | × | × |
缺省 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
8. main方法的public能不能换成private?为什么?
虽然从技术上讲,main
方法可以是private
,但这样会使得程序无法正常启动,因此通常应该将其定义为public
。
9. 构造方法和普通方法的区别
编写代码的角度:没有共同点。声明格式、作用都不同。
字节码文件的角度:构造器会以<init>()方法
的形态呈现,用以初始化对象。
10. 构造器Constructor是否可被overload?
是的,构造器(Constructor)在Java中是可以被重载(overloaded)的。构造器重载的特点与方法重载相似,即可以定义多个构造器,参数列表(参数类型、数量或顺序)不同。这样可以根据不同的初始化需求创建对象。
11. 无参构造器和有参构造器的的作用和应用
无参构造器(Default Constructor)
定义
无参构造器是指不带任何参数的构造器。当你创建一个对象时,如果没有显式定义构造器,Java会自动提供一个默认的无参构造器。
作用
- 初始化默认值:可以用于为对象的属性设置默认值。
- 创建简单对象:在某些情况下,用户只需要一个简单的对象,而不需要传递参数进行初始化。
- 兼容性:如果一个类有有参构造器,但没有定义无参构造器,其他类可能在需要无参构造器时无法正常使用该类。
有参构造器(Parameterized Constructor)
定义
有参构造器是指带有一个或多个参数的构造器,允许在创建对象时传递具体的值进行初始化。
作用
- 灵活性:可以根据实际需求初始化对象的属性。
- 简化对象创建:在对象创建时可以直接传入所需的属性值,避免后续的赋值操作。
- 多个构造方式:可以与无参构造器结合使用,提供多种方式来创建对象。
应用场景
-
无参构造器:
- 当需要创建具有默认状态的对象时,如配置类、模型类等。
- 在某些框架(如JavaBean)中,要求类必须有无参构造器以支持反射和动态实例化。
-
有参构造器:
- 当对象的属性在创建时需要被初始化,特别是在涉及到多个属性时。
- 提供不同的初始化方式,以适应不同的使用场景。
12. 成员变量与局部变量的区别
1、声明位置和方式 (1)实例变量:在类中方法外 (2)局部变量:在方法体{}中或方法的形参列表、代码块中
2、在内存中存储的位置不同 (1)实例变量:堆 (2)局部变量:栈
3、生命周期 (1)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡, 而且每一个对象的实例变量是独立的。 (2)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡, 而且每一次方法调用都是独立。
4、作用域 (1)实例变量:通过对象就可以使用,本类中直接调用,其他类中“对象.实例变量” (2)局部变量:出了作用域就不能使用
5、修饰符(后面来讲) (1)实例变量:public,protected,private,final,volatile,transient等 (2)局部变量:final
6、默认值 (1)实例变量:有默认值 (2)局部变量:没有,必须手动初始化。其中的形参比较特殊,靠实参给它初始化。
13. 变量赋值和构造方法加载的优先级问题
变量显式赋值先于构造器中的赋值。
如何证明?我看的字节码文件。
14. 父类哪些成员可以被继承,属性可以被继承吗?可以或者不可以,请举下例子。
父类的属性、方法可以被继承。构造器可以被子类调用。
15. 什么是Override,与Overload的区别
Override(重写)
- 定义:在子类中重新定义父类的方法,具有相同的方法名、返回类型和参数列表。重写的目的是提供子类特定的实现,以便在调用时使用子类的版本。
- 特点:
- 只发生在继承关系中。
- 重写的方法必须与被重写的方法具有相同的参数列表。
- 可以改变方法的访问修饰符(不能更严格,只能更宽松)。
- 使用
@Override
注解可以帮助检查是否正确重写。
Overload(重载)
- 定义:在同一个类中,定义多个方法,具有相同的方法名但参数列表不同(参数类型、数量或顺序不同)。重载的目的是提供不同的方式来执行相似的操作。
- 特点:
- 不需要在继承关系中,可以发生在同一个类中或父类与子类之间。
- 方法返回类型可以不同,但不构成重载的条件。
16. Overload的方法是否可以改变返回值的类型?
在Java中,方法重载(Overload)可以改变返回值的类型,但仅仅改变返回值类型是不足以构成重载的。重载的方法必须具有不同的参数列表,即参数的数量、类型或顺序必须不同。返回值类型并不是重载的条件之一。
17. 构造器Constructor是否可被override?
构造器(Constructor)不能被重写(override),因为重写是针对继承关系中的方法,而构造器并不是从父类继承来的方法。构造器是特定于类的,用于初始化新创建的对象。
18. 为什么要有重载,我随便命名一个别的函数名不行吗?谈谈你是怎么理解的。
1. 提高可读性
- 使用相同的函数名可以直观地表达方法之间的关系。例如,一个类中有多个
add
方法可以表示不同的加法操作,这样能让代码更易读和理解。 - 如果使用不同的函数名,代码可能变得混乱和难以理解。例如,
addIntegers
,addDoubles
,addThreeIntegers
等命名方式会增加代码复杂性。
2. 减少命名冲突
- 使用相同的函数名可以减少命名空间的使用。你不需要为每个变体定义不同的名称,这样可以减少潜在的命名冲突和重复。
- 在大型项目中,可能会有多个功能相似的方法,使用重载可以更有效地管理这些方法。
19. super和this的区别
1. 含义
this
:- 指向当前对象的引用。在类的实例方法或构造器中,
this
用于引用当前对象的属性和方法。
- 指向当前对象的引用。在类的实例方法或构造器中,
super
:- 指向当前对象的父类(超类)的引用。用于访问父类的方法和属性,尤其是在子类重写父类的方法时,
super
可以用来调用父类的实现。
- 指向当前对象的父类(超类)的引用。用于访问父类的方法和属性,尤其是在子类重写父类的方法时,
2. 使用场景
this
:- 用于区分实例变量和方法参数之间的命名冲突。
- 在构造器中调用同一类中的其他构造器。
- 在实例方法中引用当前对象。
super
:- 调用父类的构造器(使用
super()
)。 - 访问父类中被子类重写的方法。
- 访问父类的属性。
- 调用父类的构造器(使用
20. 谈谈你对多态的理解
Java引用变量有两个类型:编译时类型
和运行时类型
。编译时类型由声明
该变量时使用的类型决定,运行时类型由实际赋给该变量的对象
决定。简称:编译时,看左边;运行时,看右边。
-
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
-
多态情况下,“看左边”:看的是父类的引用(父类中不具备子类特有的方法) “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)
多态的使用前提:① 类的继承关系 ② 方法的重写
21. 多态new出来的对象跟不多态new出来的对象区别在哪?
Person p = new Man(); //虚方法调用。屏蔽了子类Man类特有的属性和方法。
Man m = new Man();
22. 说说你认为多态在代码中的体现
1. 方法重写(Overriding)
当子类重写父类的方法时,可以通过父类的引用调用子类的实现。这是运行时多态的经典体现。
示例:
class Animal {
void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
public class Test {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 父类引用指向子类对象
myAnimal.sound(); // 输出: Dog barks
myAnimal = new Cat(); // 重新指向另一个子类对象
myAnimal.sound(); // 输出: Cat meows
}
}
23. ==与equals的区别
1. 比较的内容
-
==
:- 用于比较两个引用是否指向同一个对象,即判断它们的内存地址是否相同。
- 对于基本数据类型(如
int
,char
等),==
比较它们的值是否相等。
-
equals()
:- 是一个方法,通常用于比较两个对象的内容是否相等。默认情况下,
Object
类的equals()
方法比较的是引用(即与==
相同),但许多类(如String
和自定义类)会重写此方法以实现内容比较。
- 是一个方法,通常用于比较两个对象的内容是否相等。默认情况下,
2. 使用场景
-
==
:- 用于基本数据类型的值比较。
- 用于比较对象引用,以确定它们是否指向同一个实例。
-
equals()
:- 用于比较对象的实际内容,通常在需要比较对象相等性时使用。
24. 重写equals方法要注意什么?
-
明确判定两个对象实体equals()的标准。是否需要所有的属性参与。
-
对象的属性,又是自定义的类型,此属性也需要重写equals()
25. Java中所有类的父类是什么?他都有什么方法?
在Java中,所有类的父类是Object
类。每个类,无论是用户定义的类还是Java库中的类,最终都直接或间接地继承自Object
类。这意味着所有类都可以使用Object
类中定义的方法。
Object
类的常用方法
-
equals(Object obj)
- 用于比较两个对象的内容是否相等。默认实现比较的是对象的引用(即
==
)。
- 用于比较两个对象的内容是否相等。默认实现比较的是对象的引用(即
-
hashCode()
- 返回对象的哈希码值。通常与
equals()
一起使用,用于在哈希表等数据结构中处理对象。
- 返回对象的哈希码值。通常与
-
toString()
- 返回对象的字符串表示。默认实现返回对象的类名加对象的哈希码,可以被重写以提供更有意义的字符串表示。
-
getClass()
- 返回对象的运行时类信息,即该对象所属的类的
Class
对象。
- 返回对象的运行时类信息,即该对象所属的类的
-
clone()
- 创建并返回对象的一个副本。实现了
Cloneable
接口的类可以重写此方法,以支持对象克隆。
- 创建并返回对象的一个副本。实现了
-
finalize()
- 在垃圾收集器决定回收对象之前调用。可以用来释放资源,但一般不推荐使用,因为其执行时间不确定。
-
wait()
、notify()
、notifyAll()
- 这三个方法与线程的同步机制有关,通常在多线程编程中使用。
26. 静态变量和实例变量的区别?
1. 定义和存储位置
-
静态变量(Static Variable):
- 使用
static
关键字定义的变量。 - 属于类而不是某个特定的对象,存储在方法区(也称为“静态存储区”)。
- 所有对象共享同一个静态变量。
- 使用
-
实例变量(Instance Variable):
- 在类中定义,但不使用
static
关键字的变量。 - 属于每个对象,存储在堆内存中。
- 每个对象都有自己的实例变量副本,彼此独立。
- 在类中定义,但不使用
2. 生命周期
- 静态变量:
- 在类加载时被初始化,生命周期与类的生命周期相同,直到类被卸载。
- 实例变量:
- 在创建对象时被初始化,生命周期与对象的生命周期相同,当对象被垃圾回收时实例变量也随之消失。
3. 访问方式
- 静态变量:
- 可以通过类名直接访问(例如
ClassName.variableName
),也可以通过对象访问(但不推荐)。
- 可以通过类名直接访问(例如
- 实例变量:
- 必须通过对象实例来访问(例如
objectName.variableName
)。
- 必须通过对象实例来访问(例如
4. 共享特性
- 静态变量:
- 所有对象共享同一个静态变量的值,改变一个对象的静态变量值,会影响所有对象。
- 实例变量:
- 每个对象有自己的实例变量,不同对象之间的实例变量相互独立,改变一个对象的实例变量不会影响其他对象。
27. 静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
1. 静态属性(Static Variables)
- 继承:静态属性可以被继承。当子类继承父类时,子类也会有对父类静态属性的访问权限。
- 重写:静态属性不能被重写。虽然子类可以定义一个同名的静态属性,但这并不是真正的重写,而是隐藏了父类的静态属性。访问子类或父类的静态属性时,使用类名来明确指向。
2. 静态方法(Static Methods)
- 继承:静态方法可以被继承。子类可以访问父类的静态方法,但通常使用父类名来调用。
- 重写:静态方法不能被重写。与静态属性一样,子类可以定义一个同名的静态方法,但这并不是重写,而是隐藏了父类的静态方法。访问时也应使用类名来指明。
28. 是否可以从一个static方法内部发出对非static方法的调用?
只能通过对象来对非静态方法的调用。
29. 被static修饰的成员(类、方法、成员变量)能否再使用private进行修饰?
是的,被static
修饰的成员(类、方法、成员变量)可以同时使用private
修饰。实际上,private
和static
是可以结合使用的,它们分别控制不同的访问和存储特性。
1. private
修饰符
private
修饰符表示该成员只能在定义它的类内部访问,外部类和子类无法直接访问该成员。
2. static
修饰符
static
修饰符表示该成员属于类而不是类的实例。静态成员在内存中只存在一份,所有实例共享这份数据。
30. 知道哪些设计模式?
设计模式是解决特定问题的通用解决方案。常见的设计模式主要分为三大类:创建型、结构型和行为型。以下是一些常见的设计模式:
创建型模式
- 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问。
- 工厂模式(Factory Method):定义一个创建对象的接口,让子类决定实例化哪个类。
- 抽象工厂模式(Abstract Factory):提供一个接口,用于创建一组相关或相互依赖的对象,而无需指定具体类。
- 建造者模式(Builder):将一个复杂对象的构建过程抽象化,使得同样的构建过程可以创建不同的表示。
- 原型模式(Prototype):通过复制现有的实例来创建新对象,而不是通过构造函数。
结构型模式
- 适配器模式(Adapter):将一个类的接口转换成客户端所期望的另一种接口,使得原本由于接口不兼容而无法一起工作的类可以一起工作。
- 装饰者模式(Decorator):通过将对象包装在另一个对象中来动态地添加行为或功能。
- 代理模式(Proxy):为其他对象提供一个代理,以控制对该对象的访问。
- 桥接模式(Bridge):将抽象部分与其实现部分分离,使它们可以独立变化。
- 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构,客户端可以一致地使用单个对象或组合对象。
31. 开发中都用到了那些设计模式?用在什么场合?
行为型模式
- 策略模式(Strategy):定义一系列算法,将每个算法封装起来,使得它们可以互换。
- 观察者模式(Observer):定义一种一对多的依赖关系,当一个对象状态改变时,所有依赖于它的对象都会得到通知并自动更新。
- 状态模式(State):允许对象在内部状态改变时改变其行为。
- 命令模式(Command):将请求封装成一个对象,从而可以用不同的请求对客户进行参数化。
- 迭代器模式(Iterator):提供一种方法顺序访问聚合对象中的元素,而不暴露该对象的内部表示。
1. 单例模式(Singleton)
- 应用场合:当需要确保一个类只有一个实例,并提供全局访问时,例如配置管理器、日志记录器或数据库连接池。
2. 工厂模式(Factory Method)
- 应用场合:当系统需要创建对象但不知道具体类型时,例如在游戏中创建不同类型的角色或形状。
3. 抽象工厂模式(Abstract Factory)
- 应用场合:当需要创建一系列相关对象而不指定其具体类时,例如跨平台界面的主题创建,或创建多种数据库连接。
4. 建造者模式(Builder)
- 应用场合:当需要创建复杂对象且构建过程需要独立于对象的表示时,例如创建复杂的用户界面或构建复杂的文档。
5. 适配器模式(Adapter)
- 应用场合:当需要使不兼容的接口能够一起工作时,例如在旧系统与新系统之间创建适配层。
6. 装饰者模式(Decorator)
- 应用场合:当需要动态地添加功能或行为时,例如在图形界面中添加滚动条或边框。
7. 代理模式(Proxy)
- 应用场合:当需要控制对对象的访问,例如懒加载、权限控制或远程对象访问。
8. 策略模式(Strategy)
- 应用场合:当需要在运行时选择算法或策略时,例如在排序、压缩或其他算法选择中使用。
9. 观察者模式(Observer)
- 应用场合:当一个对象的状态变化需要通知其他多个对象时,例如在事件驱动的用户界面或实时数据更新系统中。
10. 状态模式(State)
- 应用场合:当一个对象的行为依赖于其状态,并且需要在运行时根据状态改变行为时,例如状态机的实现、游戏角色的状态管理。
11. 命令模式(Command)
- 应用场合:当需要将请求封装为对象,以支持请求的参数化和撤销操作时,例如在图形编辑器中实现操作历史记录。
12. 迭代器模式(Iterator)
- 应用场合:当需要访问集合对象的元素而不暴露其内部表示时,例如在列表、集合或数组等数据结构的遍历中。
32. main()方法中是否可以调用非静态方法?
只能通过对象来对非静态方法的调用。
33. 类的组成和属性赋值执行顺序?
1、声明成员变量的默认初始化值
2、显示初始化、多个初始化块依次被执行
3、构造器再对成员进行初始化操作
4、通过对象.属性或对象.方法的方式,可多次给属性赋值
34. 静态代码块,普通代码块,构造方法,从类加载开始的执行顺序?
静态代码块 --> 普通代码块 --> 构造器
35. 描述一下对final理解
1. final
变量
- 定义:
final
修饰的变量一旦被赋值后,其值就不可再修改。这适用于基本数据类型和引用数据类型。 - 应用场合:
- 常量定义:用于定义常量,例如
final int MAX_VALUE = 100;
。 - 引用不可更改:如果
final
修饰的是引用类型的变量,则引用不可更改,但对象的内部状态可以修改。
- 常量定义:用于定义常量,例如
2. final
方法
- 定义:
final
修饰的方法不能被子类重写。这可以防止在子类中对某些关键方法的改变。 - 应用场合:用于保持方法的行为不变,确保某些关键逻辑不会被子类修改。
3. final
类
- 定义:
final
修饰的类不能被继承。即不能创建该类的子类。 - 应用场合:用于设计不希望被扩展的类,例如
String
类。
36. 判断题:使用final修饰一个变量时,是引用不能改变,引用指向的对象可以改变?
引用不能改变。
引用指向的对象实体中的属性,如果没有使用final修饰,则可以改变。
37. 判断题:final不能用于修饰构造方法?
正确,final
不能用于修饰构造方法。在Java中,构造方法的目的是用于创建类的实例,不能被重写,因此不需要使用final
修饰。final
关键字的主要用途是限制变量、方法和类的可修改性,而构造方法本身不具备被重写的特性。
38. final或static final 修饰成员变量,能不能进行++操作?
final
或static final
修饰的成员变量在Java中不能进行自增操作(++
)。这是因为:
-
final
变量:- 一旦被赋值,
final
变量的值不能被修改。自增操作实际上是先读取变量的值,再对其进行修改,所以会导致对final
变量的尝试修改,从而产生编译错误。
- 一旦被赋值,
-
static final
变量:- 同样地,
static final
变量属于类并且在类加载时被赋值,一旦赋值后其值也不可更改。自增操作会违反这一规则。
- 同样地,
39. 什么是抽象类?如何识别一个抽象类?
使用abstract修饰。
40. 为什么不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法?
1. 属性
- 原因:
abstract
用于方法,表示方法没有实现,而属性是存储数据的容器,没有“实现”这一说。因此,不能将abstract
用于属性。
2. 私有方法
- 原因:私有方法只能在定义它的类内部访问,子类无法访问。这与
abstract
的目的相悖,因为abstract
方法旨在供子类实现。如果一个方法是私有的,子类无法重写它。
3. 构造器
- 原因:构造器用于创建对象的实例,不能被重写。抽象方法的设计目的在于子类提供实现,而构造器的角色是初始化对象,无法进行实现,因此不能声明为
abstract
。
4. 静态方法
- 原因:静态方法是与类相关的,而不是与实例相关的。抽象方法是实例的方法,设计为由子类实现,因此不能将静态方法声明为
abstract
。
5. final
方法
- 原因:
final
方法被声明为不可重写。abstract
方法则要求子类提供实现,二者的目的相悖,因此一个方法不能同时是final
和abstract
。
41. 接口与抽象类的区别?
1. 定义和实现
-
接口:
- 只包含方法的声明(抽象方法)和常量(静态常量),没有方法的实现(Java 8及以上版本的接口可以有默认方法和静态方法的实现)。
- 使用
interface
关键字定义。
-
抽象类:
- 可以包含抽象方法(没有实现)和具体方法(有实现),以及成员变量和构造器。
- 使用
abstract class
关键字定义。
2. 继承
-
接口:
- 一个类可以实现多个接口(支持多重继承),使用
implements
关键字。 - 接口之间可以继承。
- 一个类可以实现多个接口(支持多重继承),使用
-
抽象类:
- 一个类只能继承一个抽象类(不支持多重继承),使用
extends
关键字。 - 抽象类之间可以继承。
- 一个类只能继承一个抽象类(不支持多重继承),使用
3. 访问修饰符
- 接口:
- 接口中的方法默认是
public
,不能使用其他访问修饰符,常量默认是public static final
。
- 接口中的方法默认是
- 抽象类:
- 抽象类中的方法可以使用多种访问修饰符(
public
、protected
、private
),并且可以有成员变量。
- 抽象类中的方法可以使用多种访问修饰符(
4. 构造器
- 接口:
- 不能有构造器,因为接口不能被实例化。
- 抽象类:
- 可以有构造器,允许在子类实例化时进行初始化。
5. 用途
- 接口:
- 用于定义功能的契约,适合于行为的抽象,强调“能做什么”,不关注如何做。
- 抽象类:
- 用于定义某一类对象的基本特征和共同行为,适合于共享代码和状态,强调“是什么”。
42. 接口是否可继承接口?抽象类是否可实现implements)接口?抽象类是否可继承实现类(concrete class)?
1. 接口是否可继承接口?
- 是的:接口可以继承其他接口。一个接口可以扩展多个其他接口,通过使用
extends
关键字。子接口会继承父接口的所有抽象方法。
2. 抽象类是否可实现接口?
- 是的:抽象类可以实现一个或多个接口,使用
implements
关键字。在抽象类中,可以选择实现接口中的部分或全部抽象方法,也可以不实现,留待子类去实现。
3. 抽象类是否可继承实现类(concrete class)?
抽象类可以继承具体类,但不能直接“实现”具体类,子类需要实现抽象类中的抽象方法。
43. 接口可以有自己属性吗?
可以。必须是public static final的
但不能有实例属性。常量可以在实现该接口的类中访问,但无法修改。
44. 访问接口的默认方法如何使用
使用实现类的对象进行调用。而且实现类还可以重写此默认方法。
45. 内部类有哪几种?
1. 成员内部类(Member Inner Class)
- 定义:在一个类的内部定义的类,属于外部类的一个成员。
- 访问权限:可以访问外部类的所有成员(包括私有成员)。
- 创建实例:需要先创建外部类的实例,再创建成员内部类的实例。
2. 静态内部类(Static Inner Class)
- 定义:在一个类的内部定义的类,使用
static
修饰。 - 访问权限:只能访问外部类的静态成员,不能访问外部类的实例成员。
- 创建实例:可以直接通过外部类的类名创建静态内部类的实例。
3. 局部内部类(Local Inner Class)
- 定义:在方法内部定义的类,其作用域仅限于方法内部。
- 访问权限:可以访问外部类的成员和方法,包括私有成员。
- 创建实例:只能在定义它的方法内部创建实例。
4. 匿名内部类(Anonymous Inner Class)
- 定义:没有名字的内部类,通常用于实例化接口或抽象类,定义时直接创建。
- 用途:主要用于简化代码,例如事件处理、回调等场景。
- 创建实例:在声明的同时创建实例。
46. 内部类的特点说一下
1. 访问外部类的成员
- 内部类可以直接访问外部类的所有成员,包括私有成员。这种特性使得内部类能够轻松地访问和操作外部类的状态。
2. 与外部类的关联
- 内部类的实例与外部类的实例是紧密关联的。创建内部类的实例时,必须先创建外部类的实例。内部类可以使用外部类的实例数据。
3. 可以是静态的或非静态的
- 内部类可以是静态的(静态内部类)或非静态的(成员内部类、局部内部类和匿名内部类)。静态内部类不需要外部类的实例,可以直接通过外部类名访问。
4. 局部作用域
- 局部内部类的作用域限制在定义它的方法内部。它只能在定义它的方法中创建和使用。这种限制提高了代码的封装性和可读性。
5. 可以创建匿名内部类
- Java支持匿名内部类,允许在创建对象的同时定义一个类。匿名内部类通常用于实现接口或继承抽象类,可以简化代码,尤其是在事件处理或回调场景中。
6. 多重内部类支持
- Java支持嵌套内部类,即一个内部类可以包含其他内部类。这种嵌套关系可以使代码结构更加清晰。
7. 作用于事件处理和回调
- 内部类经常用于GUI编程中的事件处理和回调机制,因为它们可以访问外围上下文,处理事件时不需要额外的参数传递。
47. 枚举可以继承吗?
使用enum定义的,其父类就是Enum类,就不要再继承其他的类了。
48. Java基本类型与包装类的区别
基本类型直接存储值,性能较高,但不支持对象特性;而包装类将基本类型封装为对象,提供更多功能,但性能较低。选择使用基本类型还是包装类应根据具体需求而定。
49. 面向对象的特征有哪些方面?
1. 封装(Encapsulation)
- 定义:封装是将数据(属性)和操作数据的方法(行为)组合在一起,形成一个完整的对象。它还通过访问修饰符(如
private
、protected
、public
)控制外部对对象内部状态的访问。 - 好处:封装提高了代码的安全性和可维护性,使得对象的内部实现细节对外部不可见,只能通过公开的方法进行交互。
2. 继承(Inheritance)
- 定义:继承是一种机制,允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展或重写父类的方法。
- 好处:继承促进了代码重用,减少了代码的重复,并能够建立类之间的层次结构。
3. 多态(Polymorphism)
- 定义:多态是指同一个方法调用在不同对象上可以表现出不同的行为。实现多态通常有两种方式:方法重载(编译时多态)和方法重写(运行时多态)。
- 好处:多态提高了代码的灵活性和可扩展性,使得不同类的对象可以通过相同的接口进行操作。
4. 抽象(Abstraction)
- 定义:抽象是提取对象的共性,定义类的接口而忽略具体实现的细节。抽象可以通过抽象类和接口来实现。
- 好处:抽象使得程序员能够专注于对象的主要特征,简化了复杂性,便于理解和使用。
50. 谈谈你对面向对象的理解
-
面向对象的两个要素:类、对象 ---> 面向对象编程。“万事万物皆对象”。
-
面向对象的三大特征
-
接口,与类并列的结构,作为一个补充:类可以实现多个接口。