# 第 08 章:随堂复习与企业真题(面向对象 - 高级)
# 一、随堂复习
# 1. 关键字:static
static:静态的,随着类的加载而加载、执行。
static 用来修饰:属性、方法、代码块、内部类
熟悉:static 修饰的类变量、类方法与不使用 static 修饰的区别。
- 类变量:类的生命周期内,只有一个。被类的多个实例共享。
掌握:我们遇到属性或方法时,需要考虑是否声明为 static 的。
# 2. 单例模式(或单子模式)
- 经典的设计模式有 23 种
- 解决的问题:在整个软件系统中,只存在当前类的唯一实例。
- 实现方式:饿汉式、懒汉式、枚举类等
- 私有化构造器
- 提供一个当前类的实例,必须是静态的
- 提供一个获取当前类实例的方法,必须是静态的
- 对比饿汉式和懒汉式
- 饿汉式:“立即加载”,线程安全的。
- 懒汉式:"延迟加载",线程不安全。
- 需要会手写饿汉式和懒汉式
# 3. 理解 main () 方法
- public static void main(String[] args){}
- 理解 1:作为程序的入口;普通的静态方法
- 理解 2:如何使用 main () 与控制台进行数据的交互。
- 命令行:java 类名 "Tom" "Jerry" "123"
# 4. 类的成员之四:代码块
- 分类:静态代码块、非静态代码块
- 使用频率上来讲:用的比较少。
- 静态代码块:随着类的加载而执行
- 非静态代码块:随着对象的创建而执行
总结:对象的实例变量可以赋值的位置及先后顺序
① 默认初始化
② 显式初始化 或 ⑤ 代码块中初始化
③ 构造器中初始化④ 有了对象以后,通过 "对象。属性" 或 "对象。方法" 的方法进行赋值
执行的先后顺序:
① - ②/⑤ - ③ - ④
# 5. 关键字:final
最终的
用来修饰:类、方法、变量(成员变量、局部变量)
- 类:不能被继承
- 方法:不能被重写
- 变量:是一个 “常量”,一旦赋值不能修改。
# 6. 关键字:abstract
- 抽象的
- 用来修饰:类、方法
- 类:抽象类:不能实例化。
- 方法:抽象方法:没有方法体,必须由子类实现此方法。
# 7. 关键字:interface
interface:接口,用来定义一组规范、一种标准。
掌握:接口中可以声明的结构。
属性:使用
public static final
修饰,可忽略公共静态常量
方法:
jdk8 之前:只能声明抽象方法,使用
public abstract
修饰公共抽象方法
jdk8 中:声明 static 方法、default 方法。
公共静态方法、公共默认方法
jdk9 中:声明 private 方法。
私有方法
笔试题:抽象类、接口的对比。
# 8. 类的成员之五:内部类
> 成员内部类的理解
> 如何创建成员内部类的实例
> 如何在成员内部类中调用外部类的结构
> 局部内部类的基本使用(关注:如何在方法内创建匿名局部内部类的对象)
# 9. 枚举类:enum
- 掌握:使用 enum 关键字定义枚举类即可。
# 10. 注解:Annotation
框架 = 注解 + 反射 + 设计模式
Java 基础阶段:简单。
- @Override:重写
- @Deprecated:标记过时
- @SuppressWarnings:抑制编译器警告
元注解:描述注解的注解。
- @Target:描述注解的使用范围
- @Retation:描述注解的生命周期
- @Documented:描述注解被 javadoc 工具记录
- @Inherited:描述注解被子类继承
如何自定义注解。
# 11. 包装类的使用
- 掌握:基本数据类型对应的包装类都有哪些?
掌握:基本数据类型、包装类、String 三者之间的转换
省流:
基本数据类型 / 包装类 ---> String 类
String.valueOf(xxx)
String 类 ---> 基本数据类型 / 包装类
包装类.parseXxx(str)
如果 str 的内容无法正确转换为对应的基本类型,可能会抛出异常
NumberFormatException
# 12. IDEA: 快捷键和 debug
# 二、企业真题
# 2.1 static 关键字
# 1. 实例变量和静态变量的区别?(保 * 丰、* 软国际、* 软华 *、北京明 ** 信)
个数
- 实例变量:类的每一个实例都存有一份;
- 静态变量:在内存空间中只有一份,被类的所有实例所共享;
内存位置
- 实例变量:堆空间的实例实体中;
- 静态变量:
- JDK6 及之前,存放在方法区;
- JDK7 及之后,存放在堆空间;
加载 / 消亡时机
- 实例变量:随着实例的创建而加载;随着实例的消失而消失;
- 静态变量:随着类的加载而加载,而类只会加载一次;随着类的卸载而消失;
调用者
- 实例变量:实例对象
- 静态变量:类 / 实例对象
判断是否可以调用(从生命周期的角度解释)
静态变量 实例变量 类 √ × 实例对象 √ √ 使用场景
- 静态变量:类的所有实例能共享此成员变量,开发中常常将一些常量声明为静态的,如 Math.PI
# 2. 静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?(* 度)
类似问题:
> 在java中,可以重载一个static方法吗?可以覆盖一个static方法吗?(Vi*o)
静态属性、静态方法可以被继承。
静态方法可以被重载(overload)。
静态方法不能被重写(override),不存在多态性。
当父类、子类中出现同名同参数的方法时,只允许两种情况(否则编译报错):
- 都没用 static修饰:重写(override)
- 都用了 static修饰:仅仅是同名而已,不存在多态性
public class StaticTest { public static void main(String[] args) {// 尝试重写父类的静态方法:
Father father = new Son(); father.method(); // 根据阿里巴巴 Java 开发手册,应该避免通过一个类的对象引用访问此类的静态变量或静态方法,应该直接通过类名来访问。// 通过类名访问静态方法
Father.method();}
}
class Father { public static void method() { System.out.println("Father");}
}
class Son extends Father { public static void method() { System.out.println("Son");}
}
# 3. 是否可以从一个 static 方法内部发出对非 static 方法的调用?(同 * 顺)
不能直接调用非静态方法,只能通过对象来对非静态方法的调用。
# 4. 被 static 修饰的成员 (类、方法、成员变量) 能否再使用 private 进行修饰?(联 * 优势)
完全可以。
除了代码块。
因为代码块本身不能用权限修饰符来修饰
# 2.2 设计模式
# 1. 知道哪些设计模式?(* 通快递、蚂 ** 服)
单例模式
- 饿汉式
- 懒汉式
模板方法
- 抽象类
享元设计模式
- 包装类中缓存的常量对象
# 2. 开发中都用到了那些设计模式?用在什么场合?(久 * 国际物流)
略
# 2.3 main()
# 1. main () 方法的 public 能不能换成 private,为什么(凡 * 科技、顺 *)
可以改。但是改完以后就不是程序入口了。
# 2. main () 方法中是否可以调用非静态方法?(浩 * 科技)
只能通过对象来对非静态方法的调用。
# 2.4 代码块
# 1. 类的组成和属性赋值执行顺序?(航 * 拓普)
类似问题:
> Java中类的变量初始化的顺序?(*壳)
实例变量可以赋值的位置及先后顺序:
① 默认初始化
② 显式初始化 或 ⑤ 代码块中初始化
③ 构造器中初始化
④ 有了对象以后,通过 "对象。属性" 或 "对象。方法" 的方法进行赋值
执行的先后顺序:① - ②/⑤ - ③ - ④
# 2. 静态代码块,普通代码块,构造方法,从类加载开始的执行顺序?(恒 * 电子)
类似问题:
> 类加载成员变量、静态代码块、构造器的加载顺序(*科软、软**力、同*顺)
> static代码块(静态代码块)是否在类的构造函数之前被执行(联*优势)
静态代码块 --> 普通代码块 --> 构造器
# 2.5 final 关键字
# 1. 描述一下对 final 理解(华 ** 博普)
用来修饰:类、方法、变量(成员变量、局部变量)
- 类:不能被继承
- 方法:不能被重写
- 变量:是一个 “常量”,一旦赋值不能修改。
# 2. 判断题:使用 final 修饰一个变量时,是引用不能改变,引用指向的对象可以改变?(* 米)
引用不能改变。
引用指向的对象实体中的属性,如果没有使用 final 修饰,则可以改变。
# 3. 判断题:final 不能用于修饰构造方法?(联 * 优势)
是的。无意义
# 4. final 或 static final 修饰成员变量,能不能进行 ++ 操作?(佳 * 贸易)
不能。因为赋值后不能再修改了
# 2.6 抽象类与接口
# 1. 什么是抽象类?如何识别一个抽象类?(易 * 支付)
使用 abstract 修饰。
可能有抽象方法。
# 2. 为什么不能用 abstract 修饰属性、私有方法、构造器、静态方法、final 的方法?(止 ** 善)
为了语言的自洽:
不能用 abstract 修饰属性、代码块、构造器;
- 属性:被 abstract 修饰的内容都是暂未被实现的,比如类、方法。而属性不存在 "尚未被实现" 的状态,因为在声明属性时会默认初始化!
- 代码块:“尚未被实现” 的状态?那直接删掉代码块不就好了嘛...
- 构造器:abstract 在修饰方法时,要求方法体为空,要求在子类中实现该方法。而构造方法不能被子类继承,与之矛盾
不能用 abstract 修饰私有方法、静态方法、final 的方法、final 的类。
- 私有方法:子类无法访问到父类的私有方法,因此无法被子类 override,而 abstract 方法必须要被子类实现,矛盾!
- 静态方法:静态方法可以通过类名直接调用,而 abstract 方法是没有方法体的,不能被调用,矛盾!
- final 方法:final 方法不能被子类 override,同 1
- final 类:final 类不能被继承,同 1
# 3. 接口与抽象类的区别?(字 * 跳动、阿 * 校招、* 度校招、** 计算机技术及应用研究所、航 * 拓普、纬 *、招 ** 晟、汇 * 云通、数信 ** 科技、北京永 * 鼎力、上海 * 连科技)
在开发中,常看到一个类不是去继承一个已经实现好的类,而是要么继承抽象类,要么实现接口。
# 4. 接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承实现类(concrete class)?(航 * 拓普、* 蝶、深圳德 * 科技)
类似问题:
> 接口A可以继承接口B吗?接口A可以实现接口B吗?(久*国际物流)
是;
而且接口之间的继承关系是多继承的
是;
一个类实现了某接口(有两个公共抽象方法),但该类只实现了其中一个抽象方法,那么该类也就是抽象类。
是;
Object 类是所有类的父类,它本身就是实现类。
# 5. 接口可以有自己属性吗?(华 * 中盛)
可以。必须是 public static final
的
公共静态常量
# 6. 访问接口的默认方法如何使用 (上海 * 思)
使用实现类的对象进行调用。
而且实现还可以重写此默认方法。
# 2.7 内部类
# 1. 内部类有哪几种?(华油 ** 普、来 * 科技)
成员内部类
- 静态的
- 非静态的
局部内部类
- 匿名的
- 非匿名的
# 2. 内部类的特点说一下(招通 **)
类似问题:
> 说一下内部类的好处(北京楚*龙)
> 使用过内部类编程吗,有什么作用(软**力)
成员内部类的使用特征,概括来讲有如下两种角色:
- 成员内部类作为
类的成员
的角色:- 和外部类(只能使用 public、缺省)不同,内部类还可以声明为 private 或 protected;
- 可以调用外部类的结构。(注意:在静态内部类中不能使用外部类的非静态成员)
- 可以声明为 static 的;
- 成员内部类作为
类
的角色:- 可以在内部定义属性、方法、构造器等结构
- 可以继承自己的想要继承的父类,实现自己想要实现的父接口们,和外部类的父类和父接口无关
- 可以声明为 abstract 类 ,因此可以被其它的内部类继承
- 可以声明为 final 的,表示不能被继承
- 编译以后生成
OuterClass$InnerClass.class
字节码文件(也适用于局部内部类)
注意点:
外部类访问成员内部类的成员,需要 “内部类。成员” 或 “内部类对象。成员” 的方式
成员内部类可以直接使用外部类的所有成员,包括私有的数据
当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
# 8. 匿名类说一下(阿 * 校招、上海立 * 网络)
匿名类是不能有名字的类,因此不能被引用,只能在创建时用 new 语句来声明它们。
匿名类通常继承一个父类或实现一个 / 多个接口。
# 2.8 枚举类
# 1. 枚举可以继承吗?(顺 *)
使用 enum 定义的,其父类就是 java.lang.Enum 类,就不要再继承其他的类了。
# 2.9 包装类
# 1. Java 基本类型与包装类的区别(凡 * 科技)
省流:基本类型有默认值,而包装类型初始为 null。然后再根据这两个特性进行分业务使用,在阿里巴巴的规范里所有的 POJO 类必须使用包装类型,而在本地变量推荐使用基本类型。
1、在 Java 中,一切皆对象,但八大基本类型却不是对象。
2、声明方式的不同,基本类型无需通过 new 关键字来创建,而包装类型需 new 关键字。
3、存储方式及位置的不同,基本类型是直接存储变量的值保存在栈中能高效的存取,包装类型需要通过引用指向实例,具体的实例保存在堆中。
4、初始值的不同,包装类型的初始值为 null,基本类型的的初始值视具体的类型而定,比如 int 类型的初始值为 0,boolean 类型为 false;
5、使用方式的不同,比如与集合类合作使用时只能使用包装类型。
6、什么时候该用包装类,什么时候用基本类型,看基本的业务来定:这个字段允不允许 null 值,如果允许 null 值,则必然要用封装类,否则值类型就可以了,用到比如泛型和反射调用函数.,就需要用包装类!
# 2.10 综合
# 1. 谈谈你对面向对象的理解 (君 * 科技、航 * 拓普、...)
- 面向对象的两个要素:类、对象 ---> 面向对象编程。“万事万物皆对象”。
- 面向对象的三大特征:封装、继承、多态。
- 接口,与类并列的结构,作为一个补充:类可以实现多个接口。
# 2. 面向对象的特征有哪些方面? (北京楚 * 龙、深圳德 * 科技、直 * 科技、米 * 奇网络、航 * 拓普)
- 封装(Encapsulation):将对象的属性和行为封装在一个抽象的类中,对外部隐藏其内部实现细节,只暴露必要的方法接口。这样可以避免外部直接访问和修改对象的属性,保证了对象的安全性和一致性。
- 继承(Inheritance):通过一个已经存在的类来派生出一个新的类,新的类具有已有类的所有属性和方法,并且可以添加新的属性和方法,从而实现代码的重用和扩展。Java 中支持单继承和多层继承。
- 多态(Polymorphism):同一种操作作用于不同的对象上面,可以产生不同的效果。
- 编译时多态:通过方法的重载实现,指在同一个类中,有多个方法名相同的方法,但是这些方法有着不同的参数列表,在编译期我们就可以确定到底调用哪个方法。
- 运行时多态:通过方法的重写实现,子类重写父类中的方法(包括接口的实现),父类的引用不仅可以指向父类的对象,而且还可以指向子类的对象。当父类的引用指向子类的引用时,只有在运行时才能确定调用哪个方法。
- 抽象(Abstraction):抽取对象的共性,将其提取为一个抽象的类或接口,然后具体的对象通过继承或实现来实现这个抽象的类或接口。抽象可以减少代码的重复性,提高代码的复用性和可维护性。
- 接口(Interface):接口是一种特殊的抽象类,它定义了一组方法的签名,但是没有实现方法的实现。类可以实现一个或多个接口,实现接口的类必须实现接口中定义的所有方法,从而达到了代码重用和灵活性的目的。