JAVA基本数据类型知识总结
基本数据类型(Primitive Types)
类型 | 占用字节 | 默认值 | 范围 | 示例 |
---|---|---|---|---|
byte | 1 | 0 | -128 ~ 127 | byte a = 100; |
short | 2 | 0 | -32,768 ~ 32,767 | short b = 2000; |
int | 4 | 0 | -2³¹ ~ 2³¹-1 | int c = 100000; |
long | 8 | 0L | -2⁶³ ~ 2⁶³-1 | long d = 10000000000L; |
float | 4 | 0.0f | ~7位小数 | float e = 3.14f; |
double | 8 | 0.0 | ~15位小数 | double f = 3.1415926; |
char | 2 | '\u0000' | 0 ~ 65535 | char g = 'A'; |
boolean | 1bit(实际依赖JVM) | false | true / false | boolean h = true; |
引用数据类型(Reference Types)
-
类(Class)
-
接口(Interface)
-
数组(Array)
-
枚举(Enum)
-
字符串(String)
数据类型之间的转换
自动类型转换(隐式转换)
小范围 → 大范围(安全)
Java 会自动完成的转换:
byte → short → int → long → float → double
char ↗
示例:
int a = 10;
long b = a; // int自动转为long
double c = b; // long自动转为double
强制类型转换(显式转换)
大范围 → 小范围(可能丢失精度或溢出)
语法:目标类型 变量名 = (目标类型) 原始值;
示例:
double d = 3.14;
int i = (int) d; // 强制类型转换,结果为3(小数部分丢失)
long l = 10000000000L;
int i2 = (int) l; // 强制转换,有可能溢出
代码展示:
package com.hyh;
/*
* 基本数据类型转换
*/
public class BaseData {
private final static int a = 10; // 整型 4个字节
private final static long b = 100L; // 长整型 8个字节
private final static short c = 5; // 短整型 2个字节
private final static byte d = 1; // 字节型 1个字节
private final static char e = 'A'; // 字符型 2个字节
private final static boolean f = true; // 布尔型 1个字节(Java中布尔类型的大小并不固定,通常为1字节,但在实际内存中可能会有不同的实现方式)
private final static float g = 30.5f; // 单精度浮点型 4个字节
private final static double h = 20.5; // 双精度浮点型 8个字节
public static void main(String[] args) {
//隐示转换 小范围 -> 大范围 byte → short → int → long → float → double
long x = a;
//显示转换 强制类型转换
int y = (int) b; // long 转 int
//包装数据类型转换 除了包装数据类型以外 其它类型不能直接转换 需借助包装类的构造方法或静态方法
Integer intValue = 100; // int 转 Integer
int z = intValue; // Integer 转 int
//使用引用类型的方法进行转换
String str = String.valueOf(a); // int 转 String
int num = Integer.parseInt(str); // String 转 int
// 输出结果
System.out.println("隐式转换后的值: " + x);
System.out.println("显示转换后的值: " + y);
System.out.println("包装类型转换后的值: " + intValue);
System.out.println("转换后的字符串: " + str);
System.out.println("从字符串转换回整数: " + num);
// 输出基本数据类型的值
System.out.println("整型 a: " + a);
System.out.println("长整型 b: " + b);
System.out.println("短整型 c: " + c);
System.out.println("字节型 d: " + d);
System.out.println("字符型 e: " + e);
System.out.println("布尔型 f: " + f);
System.out.println("单精度浮点型 g: " + g);
System.out.println("双精度浮点型 h: " + h);
}
}
抽象类和接口
抽象类的定义
抽象类是使用 abstract
关键字修饰的类,用于被继承,不能被实例化,通常作为父类使用。
特点:
不能创建抽象类的对象
可以包含:抽象方法 + 普通方法 + 构造方法 + 成员变量
必须由子类继承并实现其全部抽象方法,否则子类也必须是抽象类
接口的定义
接口是一种特殊的类,用于定义一组“规范”或“能力”,使用 interface
关键字定义。
-
接口中默认所有方法是
public abstract
(可省略) -
不能包含构造方法
-
从 Java 8 开始,可以包含:
-
默认方法(default)
-
静态方法(static)
-
-
从 Java 9 开始,可以有 私有方法(private)
抽象类和接口的区别
抽象类 vs 接口的语法规则对比
特性 | 抽象类 | 接口 |
---|---|---|
关键字 | abstract class | interface |
是否可以有抽象方法 | ✅ | ✅ |
是否可以有普通方法 | ✅ | ✅(Java 8 开始用 default ) |
是否可以有构造函数 | ✅ | ❌ |
是否可以有成员变量 | ✅(可以任意类型) | ✅(只能是 public static final 常量) |
多继承支持 | ❌(单继承) | ✅(多实现) |
是否可以被实例化 | ❌ | ❌ |
修饰符 | 类用 abstract ,方法可加 public/protected 等 | 接口默认 public ,方法默认 public abstract |
代码
/*
* 抽象类
*/
public abstract class Animal {
//抽象方法
public abstract void run();
//普通方法 可以存在普通方法
public void speak(){};
//构造方法
public Animal(){};
//静态成员变量
public static Integer a = 10;
}
/*
* 接口 多实现
*/
public interface Flyable {
//成员变量
public static int a = 10;
//抽象方法 默认含有 public和abstract修饰符
void run();
//普通方法 含有方法体
default void speak(){};
//静态方法
static void fly() {
System.out.println("Flying...");
}
}
JAVA常用时间类
旧版时间类(java.util
和 java.text
包)
这些类在 Java 8 之前使用广泛,但存在线程不安全、设计混乱的问题。
类名 | 说明 |
---|---|
java.util.Date | 表示某一个时间点(不包含时区) |
java.util.Calendar | 更加灵活的日期时间类(可对年月日等操作) |
java.text.SimpleDateFormat | 用于格式化和解析日期字符串 |
System.currentTimeMillis() | 返回当前时间戳(毫秒值) |
//JAVA 8之前
Date date = new Date();
System.out.println("当前时间(JAVA 8之前): " +
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(date);
System.out.println("格式化后的时间(JAVA 8之前): " + f
// 当前时间戳
long timeMillis = System.currentTimeMillis();
System.out.println("当前时间戳(毫秒): " + timeM
//时间戳转换为日期
Date dateFromMillis = new Date(timeMillis);
System.out.println("时间戳转换为日期(JAVA 8之前): " + sdf.format(dateFromMillis));
Java 8 新时间 API(推荐,java.time
包)
Java 8 引入了全新的时间 API,灵感来自 Joda-Time,属于现代化设计,线程安全且易用。
类名 | 说明 |
---|---|
LocalDate | 表示日期(年-月-日),无时间 |
LocalTime | 表示时间(时:分:秒),无日期 |
LocalDateTime | 表示日期+时间,无时区 |
ZonedDateTime | 日期时间 + 时区 |
Instant | 时间戳,代表某个瞬时点 |
Period | 用于计算日期间隔(年月日) |
Duration | 用于计算时间间隔(时分秒) |
DateTimeFormatter | 用于格式化/解析日期时间 |
ChronoUnit | 提供通用单位,如 DAYS 、MONTHS |
//JAVA 8之后
LocalDate localDate = LocalDate.now();//只有日期
LocalTime localTime = LocalTime.now();//只有时间
LocalDateTime localDateTime = LocalDateTime.now();//日期+时间
Instant instant = Instant.now();
System.out.println("当前日期(JAVA 8之后)localDate: " + localDate);
System.out.println("当前时间(JAVA 8之后)localTime: " + localTime);
System.out.println("当前日期时间(JAVA 8之后)localDateTime: " + localDateTime);
System.out.println("当前时间戳(JAVA 8之后)instant: " + in
//格式化时间
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = localDateTime.format(dtf);
System.out.println("格式化后的时间(JAVA 8之后) DateTimeFormatter: " + formattedDat
//日期加减
LocalDate localDate1 = LocalDate.now().plusDays(1);// 加一天
LocalDate localDate2 = LocalDate.now().minusDays(1); // 减一天
System.out.println("加一天后的日期(JAVA 8之后): " + localDate1);
System.out.println("减一天后的日期(JAVA 8之后): " + localDate2);
场景推荐
场景 | 建议类 |
---|---|
获取当前日期 | LocalDate.now() |
获取当前时间 | LocalTime.now() |
获取当前时间戳 | Instant.now() 或 System.currentTimeMillis() |
时间加减 | LocalDateTime.plusX() |
时间间隔 | Period (日/月/年)、Duration (时/分/秒) |
格式化/解析 | DateTimeFormatter |
与数据库交互 | java.sql.Timestamp ← 可用 LocalDateTime 替代 |
String常用类
在 Java 中,String
是最常用也是最重要的类之一,它属于 java.lang
包,不需要手动导入。String
提供了大量用于字符串操作的方法,是开发中处理文本的核心工具。
String 的基本特性
特性 | 说明 |
---|---|
不可变性 | 一旦创建,内容不可更改(底层使用 final char[] 实现) |
final 类 | 不能被继承 |
常量池优化 | 字符串字面量存在字符串常量池中,节省内存 |
支持重载的操作符 | 如:+ 用于拼接字符串 |
实现了 Serializable、Comparable、CharSequence 接口 | 支持序列化、比较和字符访问等功能 |
String 的常用构造方法
//字符串的创建
String s1 = "hello"; // 直接字面量(推荐,进入字符串常量池)
String s2 = new String("hello"); // 创建新对象(堆中新的 String 实例)
char[] chars = {'h', 'e', 'l', 'l', 'o'};
String s3 = new String(chars); // 通过字符数组构造
byte[] bytes = {97, 98, 99}; //Ascii码对应的字节数组
String s4 = new String(bytes); // 通过字节数组构造
创建方式对比
创建方式 | 示例 | 存储位置 | 是否放入常量池 | 是否新建对象 | 对象可重用性 | 比较方式 == 是否为 true |
---|---|---|---|---|---|---|
字面量创建 | String s1 = "hello"; | 字符串常量池 | ✅ 是 | ❌ 否(已存在则重用) | ✅ 高 | ✅ 如果常量池中已有 |
new 关键字创建 | String s2 = new String("hello"); | 堆内存 + 常量池 | ✅ 是(底层还是会引用常量池中的字符数组) | ✅ 是(总是新建堆对象) | ❌ | ❌ 与字面量对象比较为 false |
char数组构造 | String s3 = new String(new char[]{'h','e','l','l','o'}); | 堆内存 | ❌ 否 | ✅ 是 | ❌ | ❌ |
byte数组构造 | String s4 = new String(new byte[]{97,98}); | 堆内存 | ❌ 否 | ✅ 是 | ❌ | ❌ |
intern 方法 | String s5 = s2.intern(); | 常量池 | ✅ 是 | ❌ 复用常量池中的对象 | ✅ | ✅ 若常量池中已有相同字面量 |
String 常用方法分类详解
🔎 基本判断类
方法 | 示例 | 说明 |
---|---|---|
isEmpty() | "".isEmpty() | 长度为0则返回true |
isBlank() | " ".isBlank() | Java 11+,判断空格或空字符串 |
equals(String) | str.equals("abc") | 判断内容是否相同 |
equalsIgnoreCase(String) | 忽略大小写比较 |
boolean empty = s1.isEmpty();
boolean equals = s1.equals(s2);// 比较内容是否相同
boolean equalsIgnoreCase = s1.equalsIgnoreCase(s2);
System.out.println("字符串s1是否为空: " + empty);
System.out.println("字符串s1和s2内容是否相同: " + equals);
System.out.println("字符串s1和s2内容是否相同(忽略大小写): " + equalsIgnoreCase);
📐 获取信息类
方法 | 示例 | 说明 |
---|---|---|
length() | str.length() | 返回字符串长度 |
charAt(int) | str.charAt(0) | 获取指定索引的字符 |
indexOf(String) | str.indexOf("a") | 获取第一次出现的下标 |
lastIndexOf(String) | 最后一次出现的下标 |
//获取信息方法
int length = s1.length();
char c = s1.charAt(0);// 获取第一个字符
int i = s1.indexOf("l");// 获取字符 'l' 的索引位置
int i1 = s1.lastIndexOf("l");// 获取字符 'l' 的最后一个索引位置
System.out.println("字符串s1的长度: " + length);
System.out.println("字符串s1的第一个字符: " + c);
System.out.println("字符 'l' 在字符串s1中的第一次出现位置: " + i);
System.out.println("字符 'l' 在字符串s1中的最后一次出现位置: " + i1);
✂️ 字符串截取与分割
方法 | 示例 | 说明 |
---|---|---|
substring(begin) | str.substring(5) | 截取从指定位置到末尾 |
substring(begin, end) | str.substring(0, 5) | 左闭右开区间 |
split(String) | str.split(",") | 根据正则表达式拆分成数组 |
//字符串的切割
String substring = s1.substring(2);// 从索引2开始到末尾
String substring1 = s1.substring(1, 3); // 从索引1到索引3(不包括3)
String[] ls = s1.split("l");// 按照字符 'l' 切割字符串
System.out.println("字符串s1从索引2开始的子字符串: " + substring);
System.out.println("字符串s1从索引1到索引3的子字符串: " + substring1);
System.out.println("字符串s1按照字符 'l' 切割后的结果: " + ls.length);
⚠️ 注意:
split("\\|")
要转义|
,它在正则中是特殊字符。
🔁 字符串替换与匹配
方法 | 示例 | 说明 |
---|---|---|
replace(old, new) | "a-b".replace("-", ":") | 替换字符或字符串 |
replaceAll(regex, new) | 正则替换 | |
matches(regex) | "123".matches("\\d+") | 是否匹配正则表达式 |
contains(String) | str.contains("abc") | 是否包含子串 |
//字符串的替换与匹配
String replace = s1.replace("l", "x");// 替换所有 'l' 为 'x'
boolean he = s1.contains("he");// 检查字符串是否包含 "he"
boolean startsWith = s1.startsWith("he");// 检查字符串是否以 "he" 开头
boolean endsWith = s1.endsWith("lo");// 检查字符串是否以 "lo" 结尾
System.out.println("字符串s1替换 'l' 为 'x': " + replace);
System.out.println("字符串s1是否包含 'he': " + he);
System.out.println("字符串s1是否以 'he' 开头: " + startsWith);
System.out.println("字符串s1是否以 'lo' 结尾: " + endsWith);
🎨 大小写、去空格等
方法 | 示例 | 说明 |
---|---|---|
toUpperCase() | 转大写 | |
toLowerCase() | 转小写 | |
trim() | 去除首尾空格 | |
strip() | Java 11+,支持 Unicode 空白字符的去除 | |
repeat(n) | Java 11+,重复字符串 |
//大小写 转空格
String upperCase = s1.toUpperCase();// 转为大写
String lowerCase = upperCase.toLowerCase();// 转为小写
String trim = s1.trim(); // 去除首尾空格
System.out.println("字符串s1转为大写: " + upperCase);
System.out.println("字符串s1转为小写: " + lowerCase);
System.out.println("字符串s1去除首尾空格: " + trim);
StringBuilder 与 StringBuffer
类名 | 可变? | 线程安全? | 速度 |
---|---|---|---|
String | 不可变 | 安全 | 慢(频繁拼接时效率低) |
StringBuilder | 可变 | ❌ 不安全 | 快(推荐单线程使用) |
StringBuffer | 可变 | ✅ 安全 | 稍慢(适用于多线程) |
建议:频繁拼接字符串用 StringBuilder
,例如拼接10000个字符串。
StringBuffer sbf = new StringBuffer(s1);
StringBuffer appendSbf = sbf.append("world!");
System.out.println("StringBuilder追加字符串: " + appendSbd);
System.out.println("StringBuffer追加字符串: " + appendSbf);
枚举类型
枚举的定义
枚举(enum
)是 Java 中一种特殊的类,用于表示一组固定的常量值。它是一种类型安全的替代方案,通常用于代替 public static final
常量。
基本语法
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
枚举的特点
特性 | 描述 |
---|---|
类型安全 | 不能传入无效值(编译时检查) |
可用于 switch | 简化代码逻辑 |
本质是类 | 枚举继承 java.lang.Enum |
可定义构造方法、字段、方法 | 和普通类一样扩展能力 |
默认 public static final | 所有枚举值都是常量对象 |
不可继承其他类 | 因为已继承自 Enum 类 |
枚举属性和构造方法
/*
* 用户状态枚举
*/
public enum UserStatus {
ACTIVE("Active", "1"),
INACTIVE("Inactive", "2"),
DELETED("Deleted", "3"),
SUSPENDED("Suspended", "4");
// 构造方法
UserStatus(String status, String code) {
this.status = status;
this.code = code;
}
// 获取状态
public String getStatus() {
return status;
}
public String getCode() {
return code;
}
private final String status;
private final String code;
}
/*
* 枚举类型 星期
*/
public enum DayEnum {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
}
import com.hyh.enums.UserStatus;
import static com.hyh.enums.DayEnum.*;
public class EnumTest {
public static void main(String[] args) {
//简单枚举打印
System.out.println("枚举类型的星期: "+ FRIDAY+ " "+ " "+THURSDAY+" "+" "+WEDNESDAY +
" " +" "+ TUESDAY+" "+" "+MONDAY+" "+" "+SUNDAY+" "+" "+SATURDAY);
userStatusTest();
}
//用户状态枚举使用
public static void userStatusTest() {
System.out.println("用户状态: " + UserStatus.ACTIVE.getStatus() + ", 代码: " + UserStatus.ACTIVE.getCode());
}
}
枚举和常量类的区别
特性 | 枚举 | static final 常量 |
---|---|---|
类型安全 | ✅ | ❌(可能误传) |
switch 支持 | ✅ | ❌ |
可扩展字段 | ✅ | ❌ |
面向对象 | ✅ | ❌ |
表达意义 | 清晰 | 相对不清晰 |