Java数据类型
在 Java 中,数据类型可以分为 基本数据类型 和 引用数据类型,每种类型有其独特的用途和特点。以下是对这些类型的总结:
1. 基本数据类型(Primitive Data Types)
基本数据类型是 Java 内建的 8 种数据类型,用于存储原始数据,直接存储值而非对象引用。它们分为三类:
数值类型
- 整数类型:
byte
(8 位),short
(16 位),int
(32 位),long
(64 位)。 - 浮点类型:
float
(32 位,单精度),double
(64 位,双精度)。
字符类型
char
(16 位,表示一个 Unicode 字符)。
布尔类型
boolean
(仅有true
或false
两个值)。
2. 引用数据类型(Reference Data Types)
引用类型用于表示对象和数组,存储的是对象的内存地址(引用)。
类类型(Class Types)
- 例如
String
、ArrayList
、用户自定义类等,表示具体的对象或数据结构。
接口类型(Interface Types)
- 例如
List
、Set
、Map
等,定义了行为的规范,不能直接实例化,只能被实现或继承。
数组类型(Array Types)
- 表示一组相同类型的元素。通过数组类型引用来存取数据。
3. Object
类型
Object
是 Java 中的根类,所有类都直接或间接继承自Object
。- 任何类型的对象都可以赋给
Object
类型的变量,是一个万能类型。
4. 集合类型(Collection Types)
Java 提供了强大的集合框架,用于存储和操作一组数据。主要分为:
List 接口
- 有序集合,允许重复元素,常见实现:
ArrayList
、LinkedList
。
Set 接口
- 无序集合,不允许重复元素,常见实现:
HashSet
、TreeSet
。
Queue 接口
- 队列,遵循先进先出(FIFO)原则,常见实现:
LinkedList
、PriorityQueue
。
Map 接口
- 存储键值对,允许通过键查找值,常见实现:
HashMap
、TreeMap
。
5. 其他类型
枚举类型(Enum Types)
- 用于定义一组常量,如
Day
枚举表示星期几。
泛型类型(Generic Types)
- 提供类型安全的方式来操作不同类型的数据,通常与集合类型结合使用,如
ArrayList<Integer>
。
总结表
类型 | 分类 | 示例 |
---|---|---|
基本数据类型 | 数值类型 | int , double , char |
布尔类型 | boolean |
|
引用类型 | 类类型 | String , ArrayList |
接口类型 | List , Set , Map |
|
数组类型 | int[] , String[] |
|
Object |
根类型 | 所有对象类型都继承自 Object |
集合类型 | List |
ArrayList , LinkedList |
Set |
HashSet , TreeSet |
|
Queue |
LinkedList , PriorityQueue |
|
Map |
HashMap , TreeMap |
|
其他 | 枚举类型 | enum Day { MONDAY, TUESDAY } |
泛型类型 | ArrayList<String> , Map<K, V> |
总结
Java 的数据类型分为两大类:
- 基本数据类型:包括整数、浮点数、字符、布尔类型,直接存储数据。
- 引用数据类型:包括类类型、接口类型、数组类型等,用于表示对象,存储引用(内存地址)。
理解这些数据类型及其使用场景,是学习 Java 编程的基础。
面向对象
面向对象(Object-Oriented Programming, OOP) 是一种编程范式,基于 "对象" 和 "类" 的概念,它帮助开发者更好地组织和管理代码。Java 是一种强类型的面向对象语言,面向对象的基本概念包括 类、对象、继承、多态、封装 和 抽象。这些概念是理解和应用面向对象编程的基础。
1. 类和对象
类(Class)
- 定义:类是一个蓝图或模板,用于创建对象。类定义了对象的属性和行为。
- 构成:类包含字段(属性)和方法(行为)。
class Car {// 属性(字段)String color;String model;int year;// 行为(方法)void drive() {System.out.println("The car is driving.");}void stop() {System.out.println("The car has stopped.");}
}
对象(Object)
- 定义:对象是类的实例,通过
new
关键字创建。每个对象都有自己的状态(字段)和行为(方法)。
public class Main {public static void main(String[] args) {// 创建对象Car myCar = new Car();myCar.color = "Red";myCar.model = "Toyota";myCar.year = 2020;// 调用对象的方法myCar.drive();}
}
2. 封装(Encapsulation)
封装是指将对象的状态(字段)和行为(方法)结合在一起,并隐藏对象的内部实现细节,只暴露必要的接口给外部。
特点:
- 私有化字段:使用
private
关键字使字段无法直接访问。 - 提供公共方法:通过
public
方法来访问和修改字段的值(如 getter 和 setter 方法)。
class Person {// 私有化字段private String name;private int age;// 公共的 getter 和 setter 方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {if (age > 0) {this.age = age;}}
}
3. 继承(Inheritance)
继承是面向对象的一个重要特性,允许一个类继承另一个类的属性和方法,从而实现代码复用和扩展。
特点:
- 父类(基类):被继承的类。
- 子类(派生类):继承父类的类。
super
关键字:子类可以通过super
访问父类的属性和方法。
class Animal {void sound() {System.out.println("Animal makes a sound.");}
}class Dog extends Animal {// 子类可以重写父类的方法@Overridevoid sound() {System.out.println("Dog barks.");}
}public class Main {public static void main(String[] args) {Dog dog = new Dog();dog.sound(); // 输出: Dog barks.}
}
4. 多态(Polymorphism)
多态是指同一方法在不同对象上表现出不同的行为。Java 中的多态主要有 方法重载 和 方法重写。
方法重载(Method Overloading)
- 方法名相同,但参数不同。
class Calculator {// 加法方法重载int add(int a, int b) {return a + b;}double add(double a, double b) {return a + b;}
}
方法重写(Method Overriding)
- 子类可以重写父类的方法,改变方法的行为。
class Animal {void sound() {System.out.println("Animal makes a sound.");}
}class Cat extends Animal {@Overridevoid sound() {System.out.println("Cat meows.");}
}public class Main {public static void main(String[] args) {Animal myCat = new Cat();myCat.sound(); // 输出: Cat meows.}
}
多态的优势
- 提高代码的灵活性和可扩展性。
- 允许通过父类类型的引用指向子类对象,从而实现统一操作。
5. 抽象(Abstraction)
抽象是指隐藏对象的具体实现,只保留接口或功能的描述。Java 提供了抽象类和接口来实现抽象。
抽象类(Abstract Class)
- 抽象类不能实例化,只能继承。
- 抽象类可以包含抽象方法(没有实现的方法)。
abstract class Animal {abstract void sound(); // 抽象方法void breathe() {System.out.println("Breathing...");}
}class Dog extends Animal {@Overridevoid sound() {System.out.println("Dog barks.");}
}public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.sound(); // 输出: Dog barks.}
}
接口(Interface)
- 接口只定义方法签名,不包含方法实现,类实现接口时必须提供方法的具体实现。
interface Animal {void sound(); // 接口方法
}class Dog implements Animal {@Overridepublic void sound() {System.out.println("Dog barks.");}
}public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.sound(); // 输出: Dog barks.}
}
总结
面向对象的四大基本特性是:
- 封装:将对象的状态和行为隐藏起来,外部只能通过公共方法访问。
- 继承:子类继承父类的属性和方法,实现代码重用。
- 多态:通过父类类型的引用指向不同的子类对象,实现不同的行为。
- 抽象:通过抽象类和接口定义对象的行为,隐藏具体实现。
这些特性让 Java 更易于扩展、维护和重用代码,是开发高质量、可维护系统的基础。
synchronized VS volatile
在 Java 中,synchronized
和 volatile
是两种用于处理多线程编程中共享变量访问的关键字,但它们的作用和机制有很大的区别。
1. volatile 的特点
- 主要用途: 保证线程对变量的可见性。
- 功能:
- 线程在读写
volatile
修饰的变量时,每次都直接从主内存中读取最新的值,避免从线程的工作内存中读取过时的数据。 - 禁止指令重排序优化,确保代码在多线程中按预期顺序执行。
- 线程在读写
- 限制:
- 不保证原子性:对
volatile
变量的读写是线程安全的,但复合操作(如i++
或i = i + 1
)不是线程安全的,因为这些操作包含多条指令。 - 只能修饰变量:
volatile
只能用来修饰实例变量或类变量,不能用于方法或代码块。
- 不保证原子性:对
2. synchronized 的特点
- 主要用途: 提供线程间的互斥和同步,保证代码块或方法在同一时刻只能被一个线程执行,同时也可以保证共享变量的可见性。
- 功能:
- 互斥性:线程获得锁后,其他线程必须等待锁释放才能继续执行。
- 可见性:进入同步块的线程会强制从主内存中刷新变量值,并在释放锁时将工作内存的变量值更新到主内存。
- 使用范围:
- 可以修饰方法或代码块,确保临界区的线程安全。
- 可以通过对象锁或类锁来控制线程访问。
3. 主要区别
特性 | volatile | synchronized |
---|---|---|
原子性 | 不保证原子性,只适合简单的变量赋值操作。 | 保证代码块的原子性,适合复杂的临界区代码保护。 |
可见性 | 保证变量对所有线程的可见性。 | 保证进入同步块的线程可以看到共享变量的最新值。 |
锁机制 | 不涉及锁机制,效率较高,但无法控制线程的访问顺序。 | 需要获取锁,可能会导致线程阻塞,效率较低。 |
适用范围 | 用于简单的状态标志变量或单值更新操作。 | 用于保护复杂的临界区代码或需要保证原子性的操作。 |
性能开销 | 较低(不涉及上下文切换或阻塞)。 | 较高(可能导致线程阻塞和上下文切换)。 |
用法灵活性 | 只能修饰变量。 | 可以修饰方法、代码块,使用灵活。 |
4. 选择的场景
- 使用
volatile
的场景:- 标志变量的简单状态更新(如停止线程
boolean isRunning
)。 - 配合单例模式中的双重检查锁定(Double-Checked Locking)。
- 标志变量的简单状态更新(如停止线程
- 使用
synchronized
的场景:- 需要保证代码块或方法的原子性(如对共享变量的复杂读写操作)。
- 涉及多个共享变量的操作,且需要保持一致性。
示例代码
使用 volatile
class VolatileExample {private volatile boolean running = true;public void stop() {running = false;}public void run() {while (running) {// 执行任务}}
}
使用 synchronized
class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}
总结来说,volatile
提供轻量级的线程可见性支持,而 synchronized
是功能更强大的线程控制工具,适合更复杂的场景。