java 基础知识
2024年12月27日大约 7 分钟
java 基本类型、String、关键字等内容介绍
1. Java基本数据类型
1.1 概述
Java基本数据类型是构建程序数据存储和运算的基石,分为四类八种,不同类型具有特定的取值范围、存储字节数,以适应多样的编程需求。
1.2 详细分类
数据类型 | 字节数 | 取值范围 | 示例 | 用途场景 |
---|---|---|---|---|
byte | 1 | -128 ~ 127 | byte num = 10; | 底层数据存储、网络传输字节流处理,节省内存 |
short | 2 | -32768 ~ 32767 | short age = 30; | 特定数值范围运算,对内存有一定要求的简单场景 |
int | 4 | -2147483648 ~ 2147483647 | int count = 100; | 常规整数运算,如循环控制、数组下标 |
long | 8 | -9223372036854775808 ~ 9223372036854775807 | long timestamp = 1609459200000L; | 处理大整数,如时间戳、大数据统计计数 |
float | 4 | 约 ±3.4×10³⁸ (有效数字约 7 位) | float pi = 3.14F; | 科学计算近似值,需注意精度问题,定义加 F |
double | 8 | 约 ±1.79×10³⁰⁸ (有效数字约 15 位) | double salary = 5000.50; | 默认浮点型,高精度科学、工程计算 |
char | 2 | 0 ~ 65535(Unicode 编码值) | char ch = 'A'; | 存储单个字符,文本处理 |
boolean | 1(实际因 JVM 而异) | true 、false | boolean flag = true; | 条件判断、逻辑控制 |
1.3 自动拆装箱
自动装箱:基本类型自动转为包装类,如 Integer numObj = 10;
,编译器将 int
10 包装成 Integer
。
自动拆箱:包装类自动转为基本类型,如 Integer numObj = new Integer(20); int num = numObj;
。
注意:频繁拆装箱有性能开销,如在循环内大量操作包装类集合。
1.4 浮点数与金额问题
浮点数由于二进制存储表示,存在精度丢失问题,绝不能直接用于精确金额计算。
double amount1 = 0.1;
double amount2 = 0.2;
double sum = amount1 + amount2;
// 此时 sum 可能不是精确的 0.3,而接近 0.30000000000000004
金融领域通常使用 BigDecimal
类确保金额精准。
2. String类型
Java 中 String
类的不可变性(Immutability)意味着一旦创建了 String
对象,它的值就不能被改变。这种设计有多个方面的原因和好处:
2.1.不可变性的实现
- 私有化构造函数:
String
类的构造函数是私有的,这意味着不能直接通过构造函数来修改内部的字符数组。 - final 关键字:
String
类本身以及它用来存储字符序列的字段(通常是char[] value
或者在较新的 Java 版本中为了节省空间而采用的byte[] value
和编码标志)都被声明为final
,这表示它们不能被继承或重新赋值。 - 返回新对象:所有可能改变字符串内容的方法实际上并不改变原始字符串,而是创建并返回一个新的
String
对象。
2.2.不可变性的优点
- 线程安全:由于字符串不能被修改,因此可以在多线程环境中共享同一个字符串实例,无需担心同步问题。
- 缓存散列码:因为字符串不会改变,所以它的哈希码可以被计算一次然后缓存起来,提高性能。
- 安全性:不可变对象作为参数传递时,接收方无法更改其状态,这有助于防止意外或者恶意的状态改变。
- 字符串驻留机制:Java 使用字符串驻留(String Interning)来保存唯一的字符串副本,从而节省内存。如果字符串是可变的,那么这将导致驻留池中的数据不稳定。
2.3.示例代码
String s1 = "Hello";
String s2 = s1.concat(" World"); // 这不会改变s1,而是返回一个新的String对象给s2
System.out.println(s1); // 输出: Hello
System.out.println(s2); // 输出: Hello World
在这个例子中,s1.concat(" World")
并没有改变 s1
的值;相反,它创建了一个新的 String
对象,并将其引用赋给了 s2
。
总之,String
的不可变性是 Java 设计的一个重要特性,它不仅保证了语言的安全性和可靠性,还提供了性能上的优化。
2.4. 常用方法
方法名 | 描述 | 示例 |
---|---|---|
length() | 返回字符串长度 | String str = "Hello"; int len = str.length(); |
charAt(int index) | 获取指定索引字符 | char ch = str.charAt(2); // 取 'l' |
substring(int start, int end) | 截取子串(含 start,不含 end) | String sub = str.substring(1, 4); // "ell" |
indexOf(String str) | 查找子串首次出现位置 | int pos = str.indexOf("ll"); // 2 |
lastIndexOf(String str) | 查找子串最后出现位置 | int lastPos = str.lastIndexOf("l"); // 3 |
contains(String str) | 判断是否包含子串 | boolean has = str.contains("lo"); // true |
equals(String other) | 比较字符串内容是否相等 | boolean eq = str.equals("Hello"); // true |
equalsIgnoreCase(String other) | 忽略大小写比较 | boolean ieq = str.equalsIgnoreCase("hello"); // true |
trim() | 去除首尾空白字符 | String trimStr = " Hello ".trim(); // "Hello" |
replace(char oldChar, char newChar) | 替换字符 | String replaced = str.replace('l', 'x'); // "Hexxo" |
split(String regex) | 按正则表达式分割字符串 | String[] parts = "a,b,c".split(","); // ["a", "b", "c"] |
2.5. 使用选择
- 用
""
创建空字符串,比new String()
高效,后者创建新对象。 - 连接字符串优先用
StringBuilder
或StringBuffer
(多线程):
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" Java");
String result = sb.toString();
- 比较字符串用
equals
,避免==
,==
比较引用地址,equals
比较内容。
2.6. 字符串池、常量池概念
- 字符串池:存于堆内存,存放字面量字符串。相同字面量只存一份,如
String s1 = "Hello"; String s2 = "Hello"; s1 == s2; // true
,指向同一对象。 - Class常量池:在方法区,存编译生成常量,如字符串、基本类型常量,为类加载运行供基础数据。
- 运行时常量池:方法区动态扩展,含 Class 常量解析及动态生成常量,如
String.intern()
处理后的字符串。
2.7. intern方法
intern()
将字符串入池,若池无相同串,加入并返回池内引用,有则返回池内已有引用。
String s1 = new String("world").intern();
String s2 = "world";
System.out.println(s1 == s2); // true
2.8. String长度限制
- 编译期:常量字符串受编译器限制,通常几千字节。
- 运行时:受堆内存、JVM 实现制约,创建超长串要谨慎,防
OutOfMemoryError
。
3. Java关键字
3.1. 访问控制
关键字 | 访问权限 | 示例 |
---|---|---|
public | 所有类可见 | public class MyClass {} |
private | 仅所属类可见 | private int secret; |
protected | 同包类及子类可见 | protected void method() {} |
(默认,无关键字) | 同包类可见 | class DefaultClass {} |
3.2. 类、接口、抽象相关
class
:定义类,如class Dog {}
,类是对象蓝图,含属性、方法。interface
:定义接口,如interface Shape {}
,含方法签名、常量,无实现,供多类遵循实现多态。abstract
:修饰抽象类或方法,抽象类可含抽象方法,子类必须实现,引导继承拓展,如:
abstract class Vehicle {
abstract void move();
}
3.3. 修饰符
final
:修饰类不可继承,方法不可重写,变量成常量,如:
final class FinalClass {}
class AnotherClass {
final void finalMethod() {}
final int CONSTANT = 10;
}
static
:修饰成员归类所有,可直接用类名访问,静态方法不能访问非静态成员,如:
class Utility {
static int count;
static void increment() { count++; }
}
synchronized
:用于多线程,修饰方法或块,保证同一时刻单线程访问共享资源,如:
class SharedResource {
synchronized void access() {}
}
3.4. 流程控制
if
、else
:基本条件分支,如if (condition) {} else {}
。switch
、case
、default
:多分支,如:
switch (var) {
case 1: break;
case 2: break;
default: break;
}
while
、do - while
:循环,前者先判断后循环,后者先循环后判断,如:
while (condition) {}
do {} while (condition);
for
:万能循环,如for (init; condition; update) {}
,常用于遍历数组、集合。
3.5. 异常处理
try
、catch
、finally
:异常处理铁三角,如:
try {
// 可能抛异常代码
} catch (Exception e) {
// 处理异常
} finally {
// 必执行,清理资源
}
throw
:手动抛异常,如throw new RuntimeException("Error");
。throws
:在方法声明,示警调用者方法可能抛异常,如public void riskyMethod() throws IOException {}
。
3.6. 其他
this
:类内指代当前对象,区分同名变量,调用构造函数,如:
class Person {
private int age;
public Person(int age) {
this.age = age;
}
}
super
:子类中访问父类成员、调用父类构造,如:
class Child extends Parent {
public Child() {
super();
}
void parentMethod() {
super.method();
}
}
new
:创建对象,如Object obj = new Object();
。null
:空引用,易引发空指针,操作需谨慎。