抽象类和接口
1.抽象类和接口

类比 C++:
抽象类 ≈ C++ 中的抽象基类(带纯虚函数也可带成员函数)
接口 ≈ C++ 中的纯虚接口类(全部是纯虚函数)
public 类中的成员默认是 public 吗?继承后能访问吗?
类中声明 public 并不代表它里面的字段、方法都是 public
你必须明确写出每个字段或方法的访问修饰符,否则:
类中的变量或方法默认访问权限(不加修饰符) default(包访问权限)
比如
public class A {
int x = 10; // default,只有同包可访问
public int y = 20; // public,任何类都能访问
}
子类只能访问父类的:
public 成员 ✅
protected 成员 ✅
不能访问 private ❌
default(无修饰符)成员只有同包内可以访问
子类可以重写父类的方法
可以重写 public 和 protected 方法
不能重写:
private 方法(子类根本看不到)
final 方法(禁止重写)
比如
class A {
public void say() { System.out.println("A"); }
}
class B extends A {
@Override
public void say() { System.out.println("B"); }
}
Java的传参
Java 是值传递(pass-by-value),但对象的“引用”作为值传递
点击查看代码
class MyClass {
int x = 10;
}
void modify(MyClass obj) {
obj.x = 99; // ✅ 修改原始对象的字段(有效)
obj = new MyClass(); // ❌ 重新赋值,对原始对象没影响
obj.x = 777; // 改的是新对象
}
改“对象里的东西”有效
改“引用本身”无效(不会影响原始对象指向)
对于基础类型(int、float 等):就是传值
** **Java 是“引用类型的副本”,而 C++ 默认是“值的副本”,除非你显式地传引用。
基本类型传递
Java
public class Test {
public static void change(int x) {
x = 42;
}
public static void main(String[] args) {
int a = 10;
change(a);
System.out.println(a); // ➤ 输出 10
}
}
//Java 基本类型(如 int)是值传递,所以改的是副本,不影响原值。这和C++一样
复杂类型
Java,数组传递
public class Test {
public static void change(int[] arr) {
arr[0] = 99; // 改内容:有效
arr = new int[]{1,2,3}; // 改引用:无效
}
public static void main(String[] args) {
int[] nums = {10, 20, 30};
change(nums);
System.out.println(nums[0]); // ➤ 输出 99
}
}
//Java 传的是“引用的副本”:你可以通过副本改原数组的内容,但无法改变原变量指向的对象。
C++
void change(int* arr) {
arr[0] = 99; // 改内容:有效
arr = new int[3]{1,2,3}; // 改指向:无效
}
int main() {
int nums[] = {10, 20, 30};
change(nums);
cout << nums[0] << endl; // ➤ 输出 99
}
//除非你传指针的引用 int*&,才能改指向
传String
java
public class Test {
public static void change(String s) {
s = "world"; // 修改引用
}
public static void main(String[] args) {
String str = "hello";
change(str);
System.out.println(str); // ➤ 输出 "hello"
}
}
传List
虽然 Java 没有指针,但它用“对象引用”实现了类似效果:
你可以把对象(如 List、Map、TreeNode)当成参数传递;
在方法中对对象内容的修改,会影响到外部;
但不能在方法中重新 new 一个对象再赋值回来(那只是改了局部引用)。
Java
import java.util.*;
public class Test {
public static void change(List<String> list) {
list.set(0, "new"); // ✅ 改内容
list = new ArrayList<>(); // ❌ 改引用
list.add("xxx");
}
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.add("hello");
myList.add("world");
change(myList);
System.out.println(myList); // ➤ 输出:[new, world]
}
}
//Java 传的是“引用的值”,你能通过副本修改原 List 的内容,但不能让主函数的变量指向新的 List。
代码解析:
主函数的ListmyList = new ArrayList<>();做了两件事:1. 创建一个 ArrayList 对象(比如地址是 0xAAA);2. 定义一个变量 myList,这个变量存的是对象引用(地址 0xAAA)。
myList ───► [ "hello", "world" ] (对象在堆上)
↑
地址 0xAAA
执行 change(myList) 发生了什么?
- change(myList);这行传入的是 myList 的引用值(也就是 0xAAA):
子函数里,list 是 myList 的副本引用,它们都指向同一个对象 [ "hello", "world" ]。 - list.set(0, "new");修改了list 引用所指对象的内容;
实际上,myList 和 list 都指向这个对象,所以 myList.get(0) 也变成 "new"。 - list = new ArrayList<>();这里你给 list 重新赋值,它现在指向了一个新的空对象(比如地址 0xBBB);
但 myList 仍然指向原始的 [ "new", "world" ],它完全没变!
myList ───► [ "new", "world" ] (原始对象 0xAAA)
list ───► [ "xxx" ] (新对象 0xBBB)
- System.out.println(myList);输出:[new, world]

Java 永远是 "值传递",但如果你传的是对象(数组、List 等),它的“值”是引用,所以你可以改原对象内容,但不能改变它的引用。

浙公网安备 33010602011771号