理解 TypeScript 和 Java 在类和接口上的区别很重要。

1. 基本语法对比

1.1 接口定义

TypeScript:

typescript

// TypeScript 接口
interface Person {
  name: string;
  age: number;
  email?: string;  // 可选属性
  readonly id: number;  // 只读属性
  
  // 方法签名
  greet(): string;
  
  // 索引签名
  [key: string]: any;
}

Java:

java

// Java 接口
public interface Person {
    // 常量(默认 public static final)
    String SPECIES = "Human";
    
    // 抽象方法(Java 8 之前只能是抽象方法)
    String getName();
    int getAge();
    String greet();
    
    // Java 8+ 默认方法
    default String getInfo() {
        return "Name: " + getName() + ", Age: " + getAge();
    }
    
    // Java 8+ 静态方法
    static boolean isAdult(int age) {
        return age >= 18;
    }
}

1.2 类定义

TypeScript:

typescript

// TypeScript 类
class Student implements Person {
  // 属性可以直接在构造函数中声明
  constructor(
    public name: string,
    public age: number,
    public readonly id: number,
    public studentId: string
  ) {}
  
  // 方法实现
  greet(): string {
    return `Hello, I'm ${this.name}, a student.`;
  }
  
  // 额外的方法
  study(): void {
    console.log(`${this.name} is studying.`);
  }
}

Java:

java

// Java 类
public class Student implements Person {
    // 字段声明
    private String name;
    private int age;
    private final int id;
    private String studentId;
    
    // 构造函数
    public Student(String name, int age, int id, String studentId) {
        this.name = name;
        this.age = age;
        this.id = id;
        this.studentId = studentId;
    }
    
    // 必须实现接口方法
    @Override
    public String getName() {
        return this.name;
    }
    
    @Override
    public int getAge() {
        return this.age;
    }
    
    @Override
    public String greet() {
        return "Hello, I'm " + name + ", a student.";
    }
    
    // 额外的方法
    public void study() {
        System.out.println(name + " is studying.");
    }
}

2. 核心区别详解

2.1 编译时 vs 运行时

TypeScript:

typescript

// TypeScript 接口 - 编译时检查,运行时不存在
interface Config {
  apiUrl: string;
  timeout: number;
}

const config: Config = {
  apiUrl: "https://api.example.com",
  timeout: 5000
};

// 编译为 JavaScript 后:
// const config = {
//   apiUrl: "https://api.example.com",
//   timeout: 5000
// };
// 接口 Config 完全消失!

Java:

java

// Java 接口 - 运行时存在
public interface Config {
    String getApiUrl();
    int getTimeout();
}

// 运行时可以通过反射获取接口信息
Class<Config> configClass = Config.class;
System.out.println("Interface name: " + configClass.getName());

2.2 访问修饰符

TypeScript:

typescript

class Example {
  public publicField: string;      // 任何地方可访问
  private privateField: string;    // 仅当前类可访问
  protected protectedField: string; // 当前类和子类可访问
  readonly readOnlyField: string;  // 只读
  
  // 编译时检查,运行时没有真正的私有性
}

Java:

java

public class Example {
    public String publicField;     // 任何包可访问
    private String privateField;   // 仅当前类可访问(运行时强制)
    protected String protectedField; // 当前包和子类可访问
    String packagePrivateField;    // 包内可访问(默认)
    final String finalField;       // 不可重新赋值
    
    // 运行时强制访问控制
}

2.3 多重继承

TypeScript:

typescript

// 接口可以多重继承
interface Animal {
  name: string;
}

interface Mammal {
  hasFur: boolean;
}

interface Dog extends Animal, Mammal {  // 多重继承接口
  breed: string;
}

// 类可以实现多个接口
class Labrador implements Dog, Pet {  // 实现多个接口
  name: string;
  hasFur: boolean;
  breed: string;
}

Java:

java

// Java 接口也可以多重继承
interface Animal {
    String getName();
}

interface Mammal {
    boolean hasFur();
}

interface Dog extends Animal, Mammal {  // 多重继承接口
    String getBreed();
}

// 类只能继承一个类,但可以实现多个接口
class Labrador implements Dog, Pet {  // 实现多个接口
    // 必须实现所有接口方法
}

3. 实际应用场景对比

3.1 前端 TypeScript 典型用法

typescript

// API 响应数据类型定义
interface ApiResponse<T> {
  success: boolean;
  data: T;
  message?: string;
  timestamp: number;
}

// 组件 Props 类型
interface ButtonProps {
  text: string;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
  disabled?: boolean;
}

// React 组件
const Button: React.FC<ButtonProps> = ({ text, onClick, variant = 'primary' }) => {
  return <button className={`btn btn-${variant}`} onClick={onClick}>{text}</button>;
};

3.2 后端 Java 典型用法

java

// 服务层接口
public interface UserService {
    UserDTO createUser(CreateUserRequest request);
    UserDTO getUserById(Long id);
    List<UserDTO> getAllUsers();
    void deleteUser(Long id);
}

// 服务实现
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public UserDTO createUser(CreateUserRequest request) {
        // 业务逻辑实现
        User user = userRepository.save(convertToEntity(request));
        return convertToDTO(user);
    }
    
    // 其他方法实现...
}

4. 类型系统差异

4.1 TypeScript 的结构类型

typescript

// TypeScript 看结构,不看名称
interface Point {
  x: number;
  y: number;
}

class Coordinate {
  constructor(public x: number, public y: number) {}
}

// 这可以工作!因为结构相同
function printPoint(point: Point) {
  console.log(`x: ${point.x}, y: ${point.y}`);
}

const coord = new Coordinate(10, 20);
printPoint(coord); // ✅ 可以,因为结构匹配

4.2 Java 的名义类型

java

// Java 看类型名称,不看结构
interface Point {
    int getX();
    int getY();
}

class Coordinate {
    private int x;
    private int y;
    
    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getX() { return x; }
    public int getY() { return y; }
}

void printPoint(Point point) {
    System.out.println("x: " + point.getX() + ", y: " + point.getY());
}

Coordinate coord = new Coordinate(10, 20);
// printPoint(coord); // ❌ 编译错误!Coordinate 不是 Point 类型

5. 高级特性对比

5.1 泛型

TypeScript:

typescript

// 更灵活的泛型
interface Repository<T, ID> {
  findById(id: ID): T | null;
  save(entity: T): T;
  findAll(): T[];
}

// 条件类型、映射类型等高级特性
type Partial<T> = { [P in keyof T]?: T[P] };
type Readonly<T> = { readonly [P in keyof T]: T[P] };

Java:

java

// 类型擦除的泛型
public interface Repository<T, ID> {
    T findById(ID id);
    T save(T entity);
    List<T> findAll();
}

// 运行时类型信息有限
List<String> list = new ArrayList<>();
// 运行时只知道是 List,不知道是 List<String>

5.2 装饰器(注解)

TypeScript:

typescript

// 装饰器(实验性特性)
function Injectable(target: any) {
  console.log('Injectable decorator called on:', target);
}

@Injectable
class UserService {
  // ...
}

Java:

java

// 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Injectable {
}

@Injectable
public class UserService {
    // ...
}

6. 实际项目中的选择建议

什么时候用 TypeScript 接口?

  • 数据建模:API 响应、表单数据、组件 Props

  • 函数签名:回调函数、事件处理器的类型

  • 配置对象:函数参数、类构造选项

  • 代码契约:确保对象有特定形状

什么时候用 TypeScript 类?

  • 业务逻辑:有复杂方法和状态的实体

  • 面向对象:需要继承、多态的场景

  • 实例管理:需要创建多个相似对象

  • 封装:隐藏内部实现细节

什么时候用 Java 接口?

  • API 定义:服务层、数据访问层的契约

  • 策略模式:多种算法实现的统一接口

  • 依赖注入:Spring 等框架中的 Bean 定义

  • 测试模拟:创建 Mock 对象

什么时候用 Java 类?

  • 业务实现:具体的服务、控制器、实体

  • 数据模型:JPA 实体、DTO

  • 工具类:静态方法集合

  • 组件:Spring Bean、Servlet

7. 总结对比表

特性 TypeScript Java
接口存在性 编译时,运行时消失 运行时存在
类型系统 结构类型(鸭子类型) 名义类型
访问控制 编译时检查 运行时强制
多重继承 接口可以多继承,类单继承 接口多继承,类单继承
泛型 编译时,更灵活 类型擦除,运行时有限
可选属性 原生支持 ? 需要 Optional 类
主要用途 前端开发、Node.js 后端系统、企业应用

8. 给新手的建议

  1. TypeScript 重点

    • 学会用接口定义数据结构

    • 理解类型推断和结构类型

    • 掌握泛型在函数和组件中的应用

  2. Java 重点

    • 理解接口作为契约的作用

    • 掌握面向对象设计原则

    • 学习 Spring 等框架中的接口应用

  3. 共同点

    • 都使用接口定义契约

    • 都使用类封装逻辑

    • 都支持面向对象编程

理解这些区别能帮助你在不同场景下选择合适的技术方案,写出更健壮的代码!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐