C结构体和Java类有什么区别?

10

我是Java的新手,但对C有一定了解。我想知道C结构体和Java对象以及调用它们的方法之间有哪些区别?还是它们完全等价?

例如,自行车结构体:

class BicycleDemo {
     public static void main(String[] args) {

          // Create two different Bicycle objects
          Bicycle bike1 = new Bicycle();
          Bicycle bike2 = new Bicycle();

          // Invoke methods on those objects
          bike1.changeCadence(50);
          bike1.speedUp(10);
          bike1.changeGear(2);
          bike1.printStates();

          bike2.changeCadence(50);
          bike2.speedUp(10);
          bike2.changeGear(2);
          bike2.changeCadence(40);
          bike2.speedUp(10);
          bike2.changeGear(3);
          bike2.printStates();
     }
}

我之所以问是因为它们看起来非常相似!谢谢!

4个回答

18
如果忽略方法重写,你可以将Java类和方法看作是C风格的struct和一组对这些struct进行操作的函数的组合。例如,如果你有如下类:
 public class MyJavaClass {
       private int x;
       public int getX() {
           return x;
       }
       public int setX(int value) {
           x = value;
       }
 }

这类似于编写以下C代码:

struct MyJavaClass {
    int x;
};

int MyJavaClass_getX(struct MyJavaClass* this) {
    return this->x;
}
void MyJavaClass_setX(struct MyJavaClass* this, int value) {
    this->x = value;
}
主要思想是,一个方法类似于一个函数,它将接收器对象作为隐式的“this”参数。在C中,您必须显式将接收器作为参数传递给函数,而在Java中,这通过object.method()语法隐含地完成。
如果开始介绍方法重写,这就变得有点复杂,因为调用对象上的方法取决于对象的动态类型,而不是静态类型。一种模拟方法是使用称为“虚表”或“虚函数表”的东西,因为C++中有virtual关键字。思路是每个对象都存储一个函数指针表,每个被覆盖的函数对应一个指针,并且当在对象上调用方法时,适当的函数指针将从表中选择并调用。因此,更正确的是,上面的Java对象可能看起来像这样:
struct MyJavaClass_Vtable {
    void (*getX)(struct MyJavaClass* this);
    void (*setX)(struct MyJavaClass* this, int value);
};

struct MyJavaClass {
    struct MyJavaClass_Vtable* vtable;
    int x;
};

int MyJavaClass_getX(struct MyJavaClass* this) {
    return this->x;
}
void MyJavaClass_setX(struct MyJavaClass* this, int value) {
    this->x = value;
}

/* A global instance of the vtable for MyJavaClass */
struct MyJavaClass_Vtable MyJavaClassVtableInstance = {
    &MyJavaClass_getX,
    &MyJavaClass_setX
};
无论何时创建了 MyJavaClass 的一个实例,你需要像下面这样设置它的虚函数表:
struct MyJavaClass* mjc = malloc(sizeof *mjc);
mjc->vtable = &MyJavaClassVtableInstance;

那么,在 Java 中调用函数时,可以这样写:

myJavaClass.getX();

在C语言中,它看起来像:

myJavaClass->vtable->getX(myJavaClass);

就某种意义上来说,Java类只是带有一些额外元信息的结构体。当然,对于程序员来说,它看起来完全不同 - 有封装、多态性、更严格的类型系统等等 - 但在本地代码层面上,普通的C结构体和Java类可能看起来非常相似。

希望这可以帮到你!


6

C结构体中不能有方法/函数。它只是不同数据类型的集合。可以声明变量和方法。


3
一个结构体不能从另一个结构体继承。 - Chris
1
@Chris - 说得好。C 没有继承的概念。你应该把它发表为一个答案。 - Mahesh

2
一个Java类可以定义字段(fields),与C语言结构体类似,但还具有以下附加功能:
- 如您在问题中所述,您可以向类添加方法,这些方法可以对数据进行操作。 - 您可以声明字段和方法为 `private` (以及其他一些访问设置),这意味着只有该类的其他方法才能访问它们,不能从外部代码访问。(在结构体上使用这个特性没有意义,因为无法访问私有字段 -- 只有允许使用方法时才有意义)。 - 类可以从其他类继承。除其他事项外,这还使您可以将类型 B 的对象传递给预期类型 A 的位置,前提是 B 继承自 A。
还有另一个微妙的区别。在 C 中,结构体是值类型,但在 Java 中,类是引用类型。这意味着当您复制 C 中的结构体(例如分配给变量或作为参数传递)时,它会复制所有字段,而在 Java 中,当您复制类对象时,它只会复制对该对象的引用(因此如果您修改其字段,则同时修改原始对象,而不仅仅是副本)。
在 C 中,通常使用结构体指针来模拟 Java 的引用行为。在 Java 中,您不使用指针,因为类对象已经是引用了。

1

在我看来,类与其他编程方式的主要区别在于:

这两个特性是面向对象编程中非常重要的特点。


你忘了最重要的:继承(https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) - Nitesh Borad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接