抽象类和接口

1.抽象类和接口

image
类比 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。

代码解析:
主函数的List myList = new ArrayList<>();做了两件事:1. 创建一个 ArrayList 对象(比如地址是 0xAAA);2. 定义一个变量 myList,这个变量存的是对象引用(地址 0xAAA)。

myList ───► [ "hello", "world" ]  (对象在堆上)
             ↑
           地址 0xAAA

执行 change(myList) 发生了什么?

  1. change(myList);这行传入的是 myList 的引用值(也就是 0xAAA):
    子函数里,list 是 myList 的副本引用,它们都指向同一个对象 [ "hello", "world" ]。
  2. list.set(0, "new");修改了list 引用所指对象的内容;
    实际上,myList 和 list 都指向这个对象,所以 myList.get(0) 也变成 "new"。
  3. list = new ArrayList<>();这里你给 list 重新赋值,它现在指向了一个新的空对象(比如地址 0xBBB);
    但 myList 仍然指向原始的 [ "new", "world" ],它完全没变!
myList ───► [ "new", "world" ]   (原始对象 0xAAA)
list   ───► [ "xxx" ]            (新对象 0xBBB)
  1. System.out.println(myList);输出:[new, world]

image

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

posted @ 2025-04-24 19:17  aldercy  阅读(14)  评论(0)    收藏  举报