从C语言到Java
写在前面
记录一下笔者从C转到Java的过程,可以说是一个日记。?
正文
Java与C
首先,Java语言与C语言很直观的一个不同就在于这个public class的写法,
public class C_to_Java{
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
}
没有头文件,看起来像一个函数。C语言通过头文件调用例如printf的函数,而Java靠的是自带的类
类就是“接口”,JVM自动管理依赖
当运行 java HelloWorld 时,JVM 会自动:
查找 System 类(在 rt.jar 标准库中)。
读取 out 属性(PrintStream)。
找到 println 方法的实现。
这整个过程都是在 运行时 完成的,不需要编译时就知道所有细节
(搜的,doge)
Java的 main 方法:程序的入口
所有 Java 程序都必须有一个 main 方法,它是程序启动的起点:
public static void main(String[] args) {
System.out.println("Hello, Java!");
}
String[] args 是一个字符串数组,用来接收用户在命令行运行程序时输入的额外信息
Java的类
类是一个自定义的数据类型,它把数据(属性)和操作这些数据的函数(方法)打包在一起。
通常一个.java文件里只能有一个public类,(类似于结构体?)并且这个类名就是文件名,但可以有多个class类。因为Java编译器根据文件名去查找public。
Java和C的不同运行过程
Java和C语言一个是解释型语言一个是编译型语言,C语言生成的可执行文件直接在操作系统上运行
预处理 -> 编译 -> 汇编 -> 链接
.i .s .o .exe
C 是静态编译语言:所有东西在编译时就确定了。(所谓静态编译,就是在程序运行之前,就已经把源代码完全翻译成机器码)
Java直接编译成字节码.class文件(类似于.o文件),字节码不是机器码,而是一种中间表示(Intermediate Representation, IR),可以跨平台运行。
【无预处理】 → 【无汇编】 → 【编译】 → 【动态链接】
编译生成 .class 字节码,运行时由 JVM 动态加载并执行。
Java类的相互调用
值得一提的是,Java的不同类之间可以相互调用,这不同于C语言。
类似于C语言的定义的头文件?
不同的是C 的头文件是“静态声明”,用于告诉编译器“函数长什么样”
Java 的 import 是“动态引用”,用于告诉 JVM “去哪里找类”。
只要是 public,且在同一个包中,或者通过 import 导入其所在包的类,就可以被访问。
假设有以下目录结构
src/
├── com/
│ └── example/ 主包
│ ├── Main.java
│ ├── Calculator.java
│ └── Printer.java
└── utils/ 另一个包
└── MathUtils.java
1.同一个包内的类互相调用(无需 import)
Calculator.java(位于 com/example/)
// src/com/example/Calculator.java
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
return a * b;
}
}
Main.java(也在 com/example/)
// src/com/example/Main.java
public class Main {
public static void main(String[] args) {
// 直接使用同一包里的类,无需 import
Calculator calc = new Calculator();
//由于 add 和 multiply 是 实例方法(Instance Methods),不是 static 的。
//所以必须通过一个对象来调用,如果方法是 static,就不需要创建对象
int sum = calc.add(5, 3); // 调用 add
int product = calc.multiply(4, 6); // 调用 multiply
System.out.println("5 + 3 = " + sum);
System.out.println("4 × 6 = " + product);
}
}
对于上面的静态方法和实例方法
| 概念 | 说明 |
|---|---|
| 对象(Object) | 代表一个具体的实体,比如“一台计算器” |
| 类(Class) | 定义了“计算器”这个类型的所有属性和行为 |
| 实例方法 | 描述“这台计算器如何工作”(如加法、乘法) |
| 静态方法 | 描述“计算器这个类型本身的特性”(如数学常数) |
静态方法不也是传参数了?那它怎么是‘类型本身’的特性?”
答案是:
静态方法可以接收参数,但它不依赖于任何具体对象。它描述的是“这个类型能做什么”,而不是“这台机器正在做什么”
| 概念 | 比喻 |
|---|---|
| 实例方法 | “这台计算器正在算一个加法” → 需要一台具体的计算器(对象) |
| 静态方法 | “所有计算器都支持加法” → 这是“计算器”这个类别本身的属性 |
实例方法:你必须有一台计算器才能用它
静态方法:你不需要任何设备,因为这是规则
(搜到,不再深究,主要在于用)
2.不同包的类调用(需要 import)
MathUtils.java(位于 utils/)
// src/utils/MathUtils.java
public class MathUtils {
public static double squareRoot(double n) {
return Math.sqrt(n);
}
public static boolean isEven(int n) {
return n % 2 == 0;
}
}
Main.java(修改后,调用 utils 包中的类)
// src/com/example/Main.java
import utils.MathUtils; // 导入外部包的类
public class Main {
public static void main(String[] args) {
// 现在可以使用 MathUtils 了
System.out.println(MathUtils.squareRoot(16)); // 4.0
System.out.println(MathUtils.isEven(7)); // false
System.out.println(MathUtils.isEven(8)); // true
}
}
3.一个类调用多个类(多个 import)
Printer.java(在 com/example/)
// src/com/example/Printer.java
import utils.MathUtils;
public class Printer {
public void printInfo() {
System.out.println("计算结果:");
System.out.println("√16 = " + MathUtils.squareRoot(16));
System.out.println("8 是偶数吗?" + MathUtils.isEven(8));
}
}
Main.java(调用 Printer)
// src/com/example/Main.java
import utils.MathUtils;
import com.example.Printer;
public class Main {
public static void main(String[] args) {
Printer p = new Printer();
p.printInfo();
}
}
这里import找文件是在指定的源码目录里找,通常IDE已经自动完成了,不是在哪里都可以的哦
Java的面向对象
以下是搜的
封装:把“数据”和“行为”关进同一个盒子里
类似于C的函数,Java中的类就是这个盒子
它的好处是:你不能随便改别人的内部数据,只能通过它提供的“接口”来操作。
继承:子类可以“继承”父类的本领
写 C,想复用代码?得复制粘贴,或者用结构体嵌套。
现在写 Java,我可以直接说:“我是一个 ScientificCalculator,我继承自 Calculator。”
public class ScientificCalculator extends Calculator {
//这里extends是继承的意思
//类似于
//Dog 继承 Animal → 狗是一种动物。
//Car 继承 Vehicle → 汽车是一种交通工具。
public double sin(double x) {
return Math.sin(x);
}
}
多态:同一个名字,不同表现
同一个方法名,根据调用的对象不同,表现不同。
// 父类
public class Animal {
public void makeSound() {
System.out.println("动物在叫");
}
}
// 子类
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("汪汪汪!");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("喵喵喵!");
}
}
@Override 是一个“提醒”注解,告诉编译器:“我这个方法是重写父类的方法”,表示重写父类。
抽象:定义“做什么”,不关心“怎么做”
以前写 C,我总得写完所有代码才能用。
现在写 Java,我可以先说:“我要一个 Shape,它必须有 area() 方法。”
具体怎么算,留给子类去决定。
public abstract class Shape {
public abstract double area(); // 抽象方法,没有实现
}
public class Circle extends Shape {
private double radius;
public Circle(double r) {
this.radius = r;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
abstract是父类留给子类去实现的一个关键字,子类如果不实现,就会报错。
| 概念 | 一句话理解 |
|---|---|
| 封装 | 把数据和方法打包,保护内部细节 |
| 继承 | 子类自动拥有父类的能力 |
| 多态 | 同一个方法,不同对象,不同行为 |
| 抽象 | 定义“应该做什么”,不规定“怎么做” |
写在最后
鉴于现在代码量不足,对于Java的很多方面的理解还很浅,以后再慢慢补充吧。不过这就是过渡的样子吧。
于2026.3.2 0:22

浙公网安备 33010602011771号