java快速学习速查(2)

java快速学习速查(2)

高速通过中ing……

本篇为变量类型,变量命名规则,修饰符,运算符

Java变量类型全面解析

变量是Java程序中最基本的存储单元,理解不同类型的变量及其特性是Java编程的基础。下面我将从实际开发角度,深入讲解Java中的各种变量类型。

一、变量类型体系

1
2
3
4
5
6
7
8
9
10
11
12
Java变量类型
├── 按声明位置分
│ ├── 成员变量(类中声明)
│ │ ├── 实例变量(非static)
│ │ └── 类变量(static)
│ └── 局部变量(方法/块中声明)
│ ├── 方法局部变量
│ ├── 代码块变量
│ └── 参数变量
└── 按数据类型分
├── 基本类型变量
└── 引用类型变量

二、局部变量详解

1. 核心特性

  • 作用域:仅在声明它的方法/代码块内有效
  • 生命周期:方法/块开始执行时创建,执行结束时销毁
  • 存储位置:栈内存
  • 初始化要求:必须显式初始化后才能使用

2. 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class LocalVarDemo {
public void calculate() {
// 方法局部变量
int result = 0; // 必须初始化
for(int i=0; i<10; i++) { // i是循环块局部变量
result += i;
}

// System.out.println(i); // 错误!i已不可访问
}

public static void main(String[] args) {
// 参数变量args也是局部变量
if(args.length > 0) {
String message = "参数存在"; // 代码块局部变量
System.out.println(message);
}
// System.out.println(message); // 错误!message已不可访问
}
}

3. 关键注意事项

  • 局部变量不能使用static修饰
  • 不同代码块中可以声明同名局部变量
  • 方法参数本质也是局部变量

三、成员变量(实例变量)深度解析

1. 核心特性

  • 作用域:整个类内部(不同访问修饰符影响外部可见性)
  • 生命周期:对象创建时初始化,对象被GC回收时销毁
  • 存储位置:堆内存(作为对象的一部分)
  • 初始化:自动赋予默认值(可显式初始化)

2. 默认值规则

数据类型 默认值
byte/short/int/long 0
float/double 0.0
char ‘\u0000’
boolean false
引用类型 null

3. 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Student {
// 实例变量
private String name; // 默认null
private int age; // 默认0
private boolean graduated; // 默认false

public Student(String name, int age) {
this.name = name; // 构造器中初始化
this.age = age;
}

public void graduate() {
graduated = true; // 方法中修改状态
int localVar = 2023; // 局部变量
}

public void printInfo() {
System.out.println(name + ":" + age + "岁," +
(graduated ? "已毕业" : "在读"));
}
}

4. 最佳实践

  • 通常设为private,通过getter/setter访问
  • 重要变量应在构造器中初始化
  • 避免过多的公有实例变量

四、类变量(静态变量)全面剖析

1. 核心特性

  • 作用域:整个类(可通过类名直接访问)
  • 生命周期:类加载时初始化,程序结束时销毁
  • 存储位置:方法区(JDK8+的元空间)
  • 共享性:所有类实例共享同一份数据

2. 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Employee {
// 实例变量
private String id;
private String name;

// 类变量
private static int nextId = 1; // 下一个可用ID
public static final String COMPANY = "ABC科技"; // 常量

public Employee(String name) {
this.id = "EMP" + String.format("%04d", nextId++);
this.name = name;
}

public static int getNextId() {
return nextId; // 静态方法访问静态变量
}

public static void main(String[] args) {
System.out.println("公司:" + Employee.COMPANY);
Employee e1 = new Employee("张三");
Employee e2 = new Employee("李四");

System.out.println(e1.id); // EMP0001
System.out.println(e2.id); // EMP0002
System.out.println("下一个ID:" + Employee.getNextId()); // 3
}
}

3. 关键注意事项

  • 静态变量不属于任何对象实例
  • 静态方法只能直接访问静态成员
  • 多线程环境下需要考虑线程安全
  • 静态常量命名推荐全大写+下划线

五、参数变量特殊机制

1. 值传递与引用传递

  • 基本类型:值传递(传递副本)
  • 引用类型:引用值传递(传递引用的副本)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ParamDemo {
public static void modify(int num, String str, int[] arr) {
num = 100;
str = "修改后";
arr[0] = 99;
}

public static void main(String[] args) {
int n = 1;
String s = "原始";
int[] a = {1, 2, 3};

modify(n, s, a);

System.out.println(n); // 1(未改变)
System.out.println(s); // "原始"(未改变)
System.out.println(Arrays.toString(a)); // [99, 2, 3](改变)
}
}

2. 可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class VarargsDemo {
public static double average(int... numbers) {
if(numbers.length == 0) return 0;
int sum = 0;
for(int num : numbers) {
sum += num;
}
return (double)sum / numbers.length;
}

public static void main(String[] args) {
System.out.println(average(1, 2, 3)); // 2.0
System.out.println(average(5, 10, 15, 20)); // 12.5
}
}

六、变量对比总结表

特性 局部变量 实例变量 类变量
声明位置 方法/块内部 类中方法外 类中方法外+static
初始化要求 必须显式初始化 自动初始化 自动初始化
默认值 无(必须初始化) 有(各类型默认值) 有(同实例变量)
作用域 声明块内部 整个类 整个类
生命周期 方法/块执行期间 对象存在期间 程序运行期间
存储位置 栈内存 堆内存(对象内) 方法区
访问方式 直接访问 对象.变量名 类名.变量名
线程安全 天然线程安全 不安全 不安全
共享性 不共享 对象间不共享 全局共享

七、变量使用最佳实践

1. 命名规范

  • 遵循驼峰命名法(局部/实例变量小写开头,类变量全大写)
  • 见名知意(避免单字符命名,除临时变量)
  • 避免使用$和_开头

2. 作用域最小化

  • 尽量缩小变量作用域(优先使用局部变量)
  • 避免不必要的成员变量

3. 初始化策略

  • 局部变量:声明时立即初始化
  • 实例变量:构造器中初始化关键变量
  • 类变量:静态代码块中初始化复杂静态变量

4. 线程安全考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Counter {
// 非线程安全
private static int count1 = 0;

// 线程安全方案1:volatile
private static volatile int count2 = 0;

// 线程安全方案2:Atomic
private static AtomicInteger count3 = new AtomicInteger(0);

// 线程安全方案3:同步
private static int count4 = 0;
public static synchronized void increment() {
count4++;
}
}

八、典型面试问题解析

问题1:以下代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
public class VariableQuiz {
static int x = 10;
int y = 20;

public static void main(String[] args) {
VariableQuiz v1 = new VariableQuiz();
v1.x = 100;
v1.y = 200;

VariableQuiz v2 = new VariableQuiz();
System.out.println(v2.x + " " + v2.y);
}
}

答案:输出”100 20”。因为x是静态变量被所有实例共享,y是实例变量每个对象独立。

问题2:为什么局部变量必须初始化?

解析:Java设计者为了避免因未初始化变量导致的不可预测行为。成员变量有默认值是为了对象创建的合理性,而局部变量作用域小,强制初始化能减少错误。

问题3:以下哪种变量线程安全?

A. 局部变量
B. 实例变量
C. 静态变量
答案:A。局部变量存储在栈中,每个线程有自己的栈空间。

Java变量命名规范深度解析

良好的命名规范是编写可读性强、可维护性高的Java代码的基础。下面我将全面系统地讲解Java中各类变量的命名规则和最佳实践。

一、命名基础规则

1. 通用命名原则

  • 合法字符:字母、数字、下划线和美元符号($)
  • 开头限制:不能以数字开头
  • 长度限制:理论上无限制,但建议不超过50个字符
  • 大小写敏感myVarmyvar是不同的变量
  • 关键字规避:不能使用Java保留字(如class, int等)

2. 命名风格对比

命名风格 示例 适用场景
小驼峰(lowerCamel) studentName 变量、方法名
大驼峰(UpperCamel) StudentService 类名、接口名
蛇形(SNAKE_CASE) MAX_VALUE 常量
匈牙利(不推荐) strFirstName 旧代码(现代Java不推荐)

二、具体变量类型命名规范

1. 局部变量命名

  • 规则:小驼峰,简短且描述性
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    int itemCount = 0;
    String customerName = "张三";
    double totalPrice = calculateTotal();

    // 临时变量可用单字符(限于非常短的作用域)
    for(int i=0; i<10; i++) {
    // ...
    }

2. 实例变量命名

  • 规则:小驼峰,反映对象状态
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    public class Student {
    private String studentId; // 学号
    private boolean isGraduated; // 是否毕业
    protected String major; // 专业(protected示例)

    // boolean类型推荐is/has/can前缀
    private boolean hasScholarship;
    }

3. 静态变量命名

  • 规则
    • 常规静态变量:小驼峰
    • 常量:全大写+下划线
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    public class Config {
    // 常规静态变量
    private static int instanceCount = 0;

    // 常量
    public static final int MAX_CONNECTIONS = 100;
    public static final String DEFAULT_ENCODING = "UTF-8";
    }

4. 参数变量命名

  • 规则:小驼峰,明确表达参数用途
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    public void registerUser(String userName, String passwordHash) {
    // ...
    }

    // 布尔参数推荐使用"is/has/can"前缀
    public void setActive(boolean isActive) {
    // ...
    }

5. 泛型类型参数

  • 规则:单个大写字母,常用约定:
    • E - 集合元素
    • K - 键
    • V - 值
    • T - 类型
    • S, U - 第二、第三类型
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Box<T> {
    private T content;

    public void setContent(T content) {
    this.content = content;
    }
    }

    public interface Map<K, V> {
    V get(K key);
    // ...
    }

三、特殊场景命名规范

1. 集合类型变量

  • 推荐后缀:List/Set/Map等类型指示
  • 示例
    1
    2
    3
    List<String> studentNameList = new ArrayList<>();
    Map<Integer, Student> studentIdMap = new HashMap<>();
    Set<Course> requiredCourseSet = new HashSet<>();

2. 布尔类型变量

  • 推荐前缀
    • is - 状态标识
    • has - 拥有关系
    • can - 能力判断
    • should - 条件判断
  • 示例
    1
    2
    3
    4
    private boolean isActive;
    private boolean hasLicense;
    private boolean canEdit;
    private boolean shouldValidate;

3. 测试代码命名

  • 方法名:可使用下划线增强可读性
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Test
    public void isAdult_AgeOver18_ReturnsTrue() {
    // 测试逻辑
    }

    @Test
    public void calculatePrice_WithDiscount_AppliesDiscount() {
    // 测试逻辑
    }

四、命名禁忌与常见错误

1. 绝对避免的命名

1
2
3
4
5
6
7
8
9
10
11
12
// 反例1:无意义命名
int a = 10;
String temp = "value";

// 反例2:误导性命名
List<String> name = new ArrayList<>(); // 实际是列表却用单数

// 反例3:大小写混淆
String UserName; // 类名风格用于变量

// 反例4:数字开头
int 2ndPlace; // 编译错误

2. 不推荐的命名实践

1
2
3
4
5
6
7
8
9
10
// 1. 匈牙利命名法(类型前缀)
String strName;
int iCount;

// 2. 过长的命名
String theNameOfTheStudentWhoIsTakingTheAdvancedJavaCourse;

// 3. 不一致的缩写
int custCnt; // customerCount
int usrNum; // userNumber

五、行业标准参考

1. 官方规范

2. 常用框架命名示例

Spring示例:

1
2
3
4
5
6
7
8
9
@Repository
public class UserDaoImpl implements UserDao {
private final JdbcTemplate jdbcTemplate;

@Autowired
public UserDaoImpl(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
}

JUnit测试示例:

1
2
3
4
5
6
public class StringUtilsTest {
@Test
public void isEmpty_WhenNullInput_ReturnsTrue() {
assertTrue(StringUtils.isEmpty(null));
}
}

六、命名检查工具

1. Checkstyle配置示例

1
2
3
4
5
6
7
8
9
10
11
<module name="LocalVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>

<module name="MemberName">
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
</module>

<module name="ConstantName">
<property name="format" value="^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"/>
</module>

2. IDE模板设置

  • IntelliJ IDEAFile → Settings → Editor → Code Style → Java
  • EclipseWindow → Preferences → Java → Code Style → Formatter

七、命名重构技巧

1. 重命名快捷键

  • IntelliJ:Shift+F6
  • Eclipse:Alt+Shift+R

2. 批量重命名示例

1
2
3
4
5
6
7
// 重构前
int d; // 天数
d = 5;

// 重构后
int daysUntilExpiration;
daysUntilExpiration = 5;

3. 命名重构原则

  1. 见名知意:名称应准确表达变量用途
  2. 避免歧义:如accountList如果不是List类型就不要用
  3. 保持一致性:整个项目使用相同的命名风格
  4. 适度缩写:如num代替number可以接受,但避免过度缩写

八、典型场景命名示例

1. 计数器变量

1
2
3
4
5
// 好
int failedAttemptCount = 0;

// 不好
int counter = 0;

2. 临时变量

1
2
3
4
5
6
7
8
// 处理用户订单
public void processOrder(Order order) {
// 好的临时变量命名
double discountedPrice = calculateDiscountedPrice(order);

// 不好的命名
double temp = calculateDiscountedPrice(order);
}

3. 状态标志

1
2
3
4
5
6
7
// 好
boolean isConnected = false;
boolean hasPermission = true;

// 不好
boolean flag = false;
boolean status = true;

Java修饰符全面解析

修饰符是Java语言中用于控制类、变量、方法等元素访问权限和行为特性的关键字。下面我将系统性地讲解Java中的各种修饰符及其应用场景。

一、访问修饰符详解

1. 访问控制级别对比

修饰符 类内部 同包 不同包子类 不同包非子类 适用对象
public 类、接口、变量、方法
protected × 变量、方法、内部类
default × × 类、接口、变量、方法
private × × × 变量、方法、构造器、内部类

2. public修饰符应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 公共类(文件名必须与类名一致)
public class Animal {
// 公共变量(一般不推荐)
public String name;

// 公共方法
public void eat() {
System.out.println(name + " is eating");
}

// 公共构造方法
public Animal(String name) {
this.name = name;
}
}

// 其他包中可访问
// import com.example.Animal;
// Animal cat = new Animal("Tom");

3. protected修饰符实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example;

public class Vehicle {
protected String brand; // 子类可访问

protected void startEngine() {
System.out.println(brand + " engine starting");
}
}

// 同包类
class Garage {
void repair(Vehicle v) {
v.startEngine(); // 可访问protected方法
}
}

// 不同包子类
package com.test;
import com.example.Vehicle;

class Car extends Vehicle {
void demo() {
brand = "Toyota"; // 可访问protected变量
startEngine(); // 可访问protected方法

// Vehicle v = new Vehicle();
// v.startEngine(); // 错误!不同包非子类不能访问
}
}

4. 默认(default)修饰符示例

1
2
3
4
5
6
7
class PackagePrivateClass {  // 仅包内可见
int count; // 默认访问修饰符

void increment() {
count++;
}
}

5. private修饰符最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class BankAccount {
// 私有变量
private double balance;
private String accountNumber;

// 公共访问方法
public double getBalance() {
return balance;
}

// 私有方法(内部辅助方法)
private boolean isValidAmount(double amount) {
return amount > 0;
}

public void deposit(double amount) {
if(isValidAmount(amount)) {
balance += amount;
}
}
}

二、非访问修饰符深度解析

1. static修饰符

静态变量

1
2
3
4
5
6
7
8
9
10
11
12
13
class Employee {
private static int nextId = 1; // 类变量
private int id;

public Employee() {
id = nextId++;
}

public static int getNextId() {
// return id; // 错误!不能访问实例变量
return nextId;
}
}

静态方法

1
2
3
4
5
6
7
8
class MathUtils {
public static double circleArea(double radius) {
return Math.PI * radius * radius;
}
}

// 使用方式
double area = MathUtils.circleArea(5.0);

静态代码块

1
2
3
4
5
6
7
8
9
10
11
12
class Database {
private static Connection conn;

static {
// 类加载时执行
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb");
} catch (SQLException e) {
e.printStackTrace();
}
}
}

2. final修饰符

final变量

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Constants {
public static final double PI = 3.141592653589793;
public final int MAX_USERS; // 空白final

public Constants(int max) {
MAX_USERS = max; // 只能在构造器中赋值一次
}

void test() {
final int LOCAL_CONST = 100; // 局部final变量
// LOCAL_CONST = 200; // 错误!
}
}

final方法

1
2
3
4
5
6
7
8
9
class Parent {
public final void importantMethod() {
// 不允许子类覆盖
}
}

class Child extends Parent {
// @Override public void importantMethod() {} // 错误!
}

final类

1
2
3
4
5
6
7
final class StringUtils {  // 不能被继承
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
}

// class ExtendedUtils extends StringUtils {} // 错误!

3. abstract修饰符

抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Shape {
protected String color;

public Shape(String color) {
this.color = color;
}

// 抽象方法(无实现)
public abstract double area();

// 具体方法
public String getColor() {
return color;
}
}

抽象方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
class Circle extends Shape {
private double radius;

public Circle(String color, double radius) {
super(color);
this.radius = radius;
}

@Override
public double area() {
return Math.PI * radius * radius;
}
}

4. synchronized修饰符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Counter {
private int count = 0;

// 同步方法
public synchronized void increment() {
count++;
}

// 同步块
public void add(int value) {
synchronized(this) {
count += value;
}
}
}

5. volatile修饰符

1
2
3
4
5
6
7
8
9
10
11
class SharedObject {
private volatile boolean flag = false;

public void toggleFlag() {
flag = !flag; // 原子操作
}

public boolean isFlag() {
return flag; // 直接从主内存读取
}
}

6. transient修饰符

1
2
3
4
5
6
7
class User implements Serializable {
private String username;
private transient String password; // 不被序列化

// 敏感数据不应序列化
private transient CreditCard creditCard;
}

三、修饰符组合规则

1. 合法组合示例

组合 示例 说明
public static public static void main() 主方法必须如此
public final public final class String 不可继承的公共类
protected abstract protected abstract void draw() 需要子类实现的受保护方法
private static private static Logger log 类内部使用的静态工具
public synchronized public synchronized void put() 线程安全的公共方法

2. 非法组合及原因

非法组合 原因
abstract final abstract需要继承,final禁止继承
abstract private private方法不能被子类覆盖
abstract static static方法不参与多态
final volatile final不可变,volatile需要可变
synchronized abstract 抽象方法没有实现,无法同步

四、类成员修饰符适用表

修饰符 接口 变量 方法 构造器 代码块
public ×
protected × × ×
default ×
private × × ×
static × × ×
final × × ×
abstract × × ×
synchronized × × × ×
volatile × × × × ×
transient × × × × ×

五、典型应用场景

1. 单例模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Singleton {
private static volatile Singleton instance;

private Singleton() {} // 私有构造器

public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

2. 工具类设计

1
2
3
4
5
6
7
8
9
10
11
12
13
public final class StringUtils {
// 私有构造器防止实例化
private StringUtils() {}

public static boolean isBlank(String str) {
return str == null || str.trim().isEmpty();
}

public static String reverse(String str) {
if (str == null) return null;
return new StringBuilder(str).reverse().toString();
}
}

3. 线程安全计数器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SafeCounter {
private int count;

public synchronized void increment() {
count++;
}

public synchronized int get() {
return count;
}

// 使用原子变量更高效
private AtomicInteger atomicCount = new AtomicInteger(0);

public void atomicIncrement() {
atomicCount.incrementAndGet();
}
}

六、修饰符使用最佳实践

  1. 封装原则:成员变量尽量私有,通过方法控制访问
  2. 最小权限:使用最严格的访问级别(优先private)
  3. static慎用:避免滥用导致内存泄漏和测试困难
  4. final应用:尽可能使变量不可变,减少并发问题
  5. 同步策略:优先使用并发工具类而非synchronized
  6. 抽象设计:抽象类定义框架,具体类实现细节

Java运算符全面解析

运算符是Java语言中用于执行各种操作的符号。下面我将系统地讲解Java中的各类运算符及其使用场景。

一、算术运算符

1. 基本算术运算符

运算符 名称 示例 说明
+ 加法 a + b 也可用于字符串连接
- 减法 a - b
* 乘法 a * b
/ 除法 a / b 整数相除结果取整
% 取模 a % b 取余数

代码示例:

1
2
3
4
5
6
7
8
int a = 10;
int b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3 (整数除法)
System.out.println(a % b); // 1
System.out.println(10.0 / 3); // 3.333... (浮点除法)

2. 自增/自减运算符

运算符 名称 示例 等价于
++i 前自增 int j = ++i; i = i + 1; j = i;
i++ 后自增 int j = i++; j = i; i = i + 1;
–i 前自减 int j = –i; i = i - 1; j = i;
i– 后自减 int j = i–; j = i; i = i - 1;

示例分析:

1
2
3
int x = 5;
int y = x++; // y=5, x=6
int z = ++x; // x=7, z=7

二、关系运算符

关系运算符用于比较两个值,返回布尔结果:

运算符 名称 示例 说明
== 等于 a == b 比较值是否相等
!= 不等于 a != b
> 大于 a > b
< 小于 a < b
>= 大于等于 a >= b
<= 小于等于 a <= b

注意事项:

  • 比较引用类型时,==比较的是引用地址
  • 比较字符串内容应使用equals()方法

示例:

1
2
3
4
5
6
7
8
9
int a = 10, b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a > b); // false

String s1 = "hello";
String s2 = new String("hello");
System.out.println(s1 == s2); // false (不同对象)
System.out.println(s1.equals(s2)); // true (内容相同)

三、逻辑运算符

1. 基本逻辑运算符

运算符 名称 示例 说明
&& 逻辑与 a && b 短路与
|| 逻辑或 a || b 短路或
! 逻辑非 !a 取反

短路特性示例:

1
2
3
4
int x = 5;
boolean result = (x < 4) && (x++ < 10);
// 第一个条件为false,第二个不执行
System.out.println(x); // 仍为5

2. 位运算符

运算符 名称 示例 说明
& 位与 a & b 按位与
| 位或 a | b 按位或
^ 位异或 a ^ b 相同为0,不同为1
~ 位非 ~a 按位取反
<< 左移 a << 2 左移,低位补0
>> 右移 a >> 2 右移,高位补符号位
>>> 无符号右移 a >>> 2 右移,高位补0

位运算示例:

1
2
3
4
5
6
7
8
int a = 60;    // 60 = 0011 1100
int b = 13; // 13 = 0000 1101
System.out.println(a & b); // 12 = 0000 1100
System.out.println(a | b); // 61 = 0011 1101
System.out.println(a ^ b); // 49 = 0011 0001
System.out.println(~a); // -61 = 1100 0011
System.out.println(a << 2); // 240 = 1111 0000
System.out.println(a >> 2); // 15 = 0000 1111

四、赋值运算符

1. 基本赋值运算符

运算符 示例 等价于
= a = b
+= a += b a = a + b
-= a -= b a = a - b
*= a *= b a = a * b
/= a /= b a = a / b
%= a %= b a = a % b

复合赋值示例:

1
2
3
4
int x = 10;
x += 5; // x = 15
x *= 2; // x = 30
x %= 7; // x = 2

2. 位运算赋值运算符

运算符 示例 等价于
&= a &= b a = a & b
|= a |= b a = a | b
^= a ^= b a = a ^ b
<<= a <<= b a = a << b
>>= a >>= b a = a >> b
>>>= a >>>= b a = a >>> b

五、条件运算符(三元运算符)

语法:条件 ? 表达式1 : 表达式2

示例:

1
2
3
4
int a = 10, b = 20;
int max = (a > b) ? a : b; // max = 20

String result = (score >= 60) ? "及格" : "不及格";

六、instanceof运算符

用于检查对象是否是特定类的实例:

1
2
3
4
5
6
7
8
Object obj = "hello";
System.out.println(obj instanceof String); // true
System.out.println(obj instanceof Integer); // false

class Vehicle {}
class Car extends Vehicle {}
Car car = new Car();
System.out.println(car instanceof Vehicle); // true

七、运算符优先级

下表按优先级从高到低排列:

优先级 运算符 结合性
1 () [] . 左→右
2 ! ~ ++ – +(正) -(负) 右→左
3 * / % 左→右
4 + - 左→右
5 << >> >>> 左→右
6 < <= > >= instanceof 左→右
7 == != 左→右
8 & 左→右
9 ^ 左→右
10 | 左→右
11 && 左→右
12 || 左→右
13 ?: 右→左
14 = += -= *= /= %= &= |= ^= <<= >>= >>>= 右→左

优先级示例:

1
2
int result = 5 + 3 * 2;      // 11 (乘法优先)
boolean flag = 5 > 3 && 2 < 4; // true (关系运算优先)

八、特殊运算符技巧

1. 交换变量值

1
2
3
4
5
int a = 5, b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
// 现在 a=10, b=5

2. 判断奇偶

1
2
3
4
5
if ((num & 1) == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}

3. 快速乘除2的幂次

1
2
3
int n = 8;
n = n << 1; // n*2 = 16
n = n >> 2; // n/4 = 4

九、常见问题与陷阱

  1. 整数除法

    1
    2
    double d = 5 / 2;  // 2.0 (不是2.5)
    double d2 = 5.0 / 2; // 2.5
  2. 浮点数比较

    1
    2
    3
    4
    5
    // 错误方式
    if (f1 == f2) {...}

    // 正确方式
    if (Math.abs(f1 - f2) < 1e-6) {...}
  3. 字符串比较

    1
    2
    3
    4
    String s1 = "hello";
    String s2 = new String("hello");
    System.out.println(s1 == s2); // false
    System.out.println(s1.equals(s2)); // true
  4. 运算符优先级混淆

    1
    2
    int x = 5 + 3 * 2;    // 11 不是16
    boolean b = 5 > 3 == true; // true (5>3为true,true==true)