Java-Chapter 10 Thinking in Objects
Java-Chapter 10 Thinking in Objects
问题 1:面向对象与面向过程的区别是什么?
答案:
- 面向过程:以方法为中心,解决问题时分解为具体的过程或步骤,强调方法的执行顺序。
- 面向对象:以对象为中心,强调将数据和操作整合为一个整体,关注对象的状态和行为。
解释:
面向对象的编程方式结合了面向过程的逻辑性,同时通过对象将数据和方法封装起来,便于维护和扩展。面向对象提供了更强的可扩展性、代码复用和模块化能力。
示例:
面向过程:
1
2
3
4// 计算两点之间的距离
public static double calculateDistance(double x1, double y1, double x2, double y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}面向对象:
1
2
3
4
5
6
7
8
9
10
11
12class Point {
double x, y;
Point(double x, double y) {
this.x = x;
this.y = y;
}
public double distance(Point other) {
return Math.sqrt(Math.pow(other.x - this.x, 2) + Math.pow(other.y - this.y, 2));
}
}
问题 2:实例变量与静态变量的作用域是什么?
答案:
- 实例变量:作用域是整个类,但只能通过对象访问,与具体实例绑定。
- 静态变量:作用域是整个类,与类绑定,而不是具体实例,可以通过类名访问。
解释:
两者的作用域覆盖整个类,无论变量声明在类的何处,都能被访问。但静态变量被所有对象共享,而实例变量每个对象都有独立的拷贝。
示例:
1 | class Demo { |
问题 3:关键字
this
的作用是什么?
答案:
- 用于引用当前调用对象。
- 在构造方法中可以用
this
调用同类的其他构造方法。
解释:
this
指向当前实例对象,用于在方法或构造方法中区分局部变量与实例变量。它还能实现构造方法之间的调用,避免重复代码。
示例:
区分实例变量和局部变量:
1
2
3
4
5
6
7class Person {
String name;
Person(String name) {
this.name = name; // this 引用当前实例的 name 变量
}
}调用其他构造方法:
1
2
3
4
5
6
7
8
9
10
11
12
13class Person {
String name;
int age;
Person(String name) {
this(name, 0); // 调用另一个构造方法
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
问题 4:Java如何将基本数据类型转换为对象类型?
答案:
Java通过“装箱”(boxing)将基本数据类型转换为对象类型。例如,将
int
转换为 Integer
,double
转换为
Double
,char
转换为
Character
,等等。
解释:
在Java中,包装类(如 Integer
, Double
,
Character
等)用于封装基本数据类型的值。当需要将基本类型值作为对象使用时,可以使用这些包装类。在一些情况下,Java会自动进行装箱(自动转换为对象)和拆箱(将对象转回基本类型)操作,称为自动装箱和自动拆箱。
示例:
1 | int num = 100; |
问题 5:Integer类的静态方法有哪些?
答案:
static int parseInt(String s)
:将字符串转换为整数。static Integer valueOf(String s)
:将字符串转换为Integer
对象。static Integer valueOf(int i)
:将int
转换为Integer
对象。
解释:
parseInt()
用于将字符串解析为原始int
类型。valueOf()
用于将String
或int
转换为Integer
对象。如果字符串可以转换为有效的整数,valueOf()
方法会返回一个Integer
对象。
示例:
1 | String str = "123"; |
问题
6:Integer a = 100; Integer b = 100; a == b
的结果是什么?
答案:
a == b
的结果是 true
。
解释:
- 对于
Integer
类型,Java 会缓存-128
到127
范围内的常用整数对象,因此在这个范围内,使用Integer.valueOf()
方法时会返回缓存中的对象,而不是每次都创建新的对象。 - 由于
a
和b
都被赋值为100
,而100
在-128
到127
的范围内,因此它们引用的是同一个缓存对象,因此a == b
返回true
。
示例:
1 | Integer a = 100; |
问题 7:什么是装箱(Boxing)和拆箱(Unboxing)?
答案:
- 装箱(Boxing):将基本数据类型转换为对应的包装类对象。例如,将
int
转换为Integer
。 - 拆箱(Unboxing):将包装类对象转换为对应的基本数据类型。例如,将
Integer
转换为int
。
解释:
Java
提供了自动装箱和拆箱的功能。装箱是指将基本数据类型自动包装为对象,拆箱是指将对象自动转换为基本数据类型。在许多情况下,Java
会自动进行这些转换。
示例:
1 | Integer a = 100; // 自动装箱,将 int 转为 Integer |
问题 8:String类的不可变性如何影响它的性能?
答案:
String
是不可变的,即一旦创建后其内容不能修改。这种设计提高了效率并节省内存,尤其在处理相同字符序列的多个字符串时。JVM
会对具有相同字符序列的字符串创建唯一的对象,这些对象被称为“字符串常量池”中的字符串对象。
解释:
- 不可变性:字符串一旦被创建,就无法更改其内容。如果对字符串进行修改,实际上会创建一个新的字符串对象。
- 字符串常量池:JVM 会将相同的字符串字面量共享存储,避免重复的字符串对象,从而节省内存。
示例:
1 | String str1 = "hello"; |
问题 9:正则表达式是什么?
答案:
正则表达式是用于描述字符串模式的语法,它可以用来匹配、替换、或分割字符串。
解释:
正则表达式通过特定的模式描述符,能够描述一个或多个字符的匹配规则。Java
提供了 Pattern
和 Matcher
类来支持正则表达式的操作。可以使用正则表达式执行诸如查找、替换和分割等操作。
示例:
1 | String text = "hello123world"; |
这段代码的目的是检查字符串
"hello123world"
是否符合正则表达式\\w+\\d+\\w+
的规则。
\\w+
:表示一个或多个字母、数字或下划线。\\w
是“word”的缩写,等价于[a-zA-Z0-9_]
。+
表示一个或多个。\\d+
:表示一个或多个数字。\\d
表示数字,等价于[0-9]
。正则表达式
\\w+\\d+\\w+
需要满足以下条件:
- 字符串的开始部分由一个或多个字母、数字或下划线组成(
\\w+
)。- 接下来紧跟着一个或多个数字(
\\d+
)。- 最后是一个或多个字母、数字或下划线(
\\w+
)。对于
"hello123world"
:
hello
部分符合\\w+
(字母组成)。123
部分符合\\d+
(数字组成)。world
部分符合\\w+
(字母组成)。因此,整个字符串符合这个正则表达式,
text.matches("\\w+\\d+\\w+")
的返回值是true
,最终输出true
。这就是为什么代码会输出
true
。
问题 10:StringBuilder 和 StringBuffer 有什么区别?
答案:
- StringBuilder:是一个可变的字符序列,适用于单线程环境。操作字符串时,它的性能比
String
更高。 - StringBuffer:也是一个可变的字符序列,类似于
StringBuilder
,但它是线程安全的,因此它适用于多线程环境。
解释:
- StringBuilder 和 StringBuffer
都允许对字符串进行修改(如添加、插入、删除等),但是由于线程安全的开销,
StringBuffer
比StringBuilder
稍慢。 - 如果不涉及多线程,
StringBuilder
是首选,因为它比StringBuffer
更高效。
示例:
1 | StringBuilder sb = new StringBuilder("Hello"); |