java学习篇(一)—— CPP和Java的区别之基础概念
一些感想
写在开头,如果你是一个坚定选择工作的研究生,在CPP和Java之间反复跳转,那么有以下几种情况,建议你选CPP:
- 对CPP有强大的兴趣,且组内有成熟的方向,例如:高性能计算、音频开发等方向,可以选择。
- 仅仅想找一份工作,不要跟自己过不去,Java很好,尤其是后端。
博主是在模型部署里做了一年,但是由于确实不感兴趣,荒废时间后发现自己的工作上毫无优势,最终无奈学习Java的。
Java有很明确的学习路线:Java基础--->JDBC + 数据库--->Java web---> spring--->SpringCloud + Redis + 中间件巴拉巴拉。
由于博主之前在CPP上有一些学习经验,但是网上的学习路线都是针对于零基础的,这样无疑会增加学习成本,所以想要记录一下整个学习过程,给同样苦苦挣扎的人一些帮助。
在写完这个博客之后,个人认为以下几个方面可以帮助你快速了解Java和cpp的不同:JVM、接口、引用变量类型、Object类、接口与泛型。这几个是最能体现Java面向对象编程思想的。
程序运行的区别
C++的代码想要运行就需要编译,编译过程包括:预处理、编译、汇编、连接。针对不同的操作系统和CPU架构,需要特定的编译器,例如x86和arm的指令不同,那么需要的编译工具链也不同。而Java程序的.java文件通过javac编译成.class字节码文件(不是机器码),字节码由 Java 虚拟机JVM解释或JIT编译为本地机器码运行,不同操作系统和硬件平台,只要安装了对应的 JVM,就能运行这些.class或.jar文件。综上,Java在可移植性上具有强大的优势。
因此,Java也被叫做解释型语言,Java源代码被编译成字节码后,需要解释这些字节码才能在计算机上运行。
JVM带来的优势
cpp想要实现什么功能,都是以调用的形式,例如调用操作系统Socket的接口、操作系统thread的接口、调用自己写的接口,且由于依赖于底层的框架和操作系统,因此cpp针对一些功能实现没有相对应的库,例如实现webserver,就需要自己实现http协议、路由分发、多线程和数据库等等,而这些在Java里只需要对应的模块就可以。根本原因是,Java的可移植性更强,使得它可以做一套统一的接口供不同的平台调用。
面向过程与面向对象
这是两个有点抽象的概念,但观察.cpp和.java的程序,一个显著的差异就是main()函数的位置,在.java程序里,main()只能定义在类里,或者说,所有代码都必须属于类。回忆一下cpp代码,.h是头文件,定义类,成员函数,成员变量等,.cpp是我们想要实现的功能。功能被拆解成了无数个子任务,最终在main()里顺序执行,这就是面向过程。Java 是“纯面向对象语言”(除了基本类型),强调“一切皆类”,所以main也必须属于某个类,即使它是程序入口点。Java将所有的函数定义为了方法(Method),方法的调用必须通过对象或者类来实现,而CPP中则可以通过直接调用。Java的接口机制使得它能够很好的对对象进行封装,Object类使得JVM的任何对象都可以被方法统一调用。
Java代码的执行方式包括两种,分别是:
| 执行方式 | 描述 |
|---|---|
| 解释执行 | 最初由 JVM 中的 解释器 一条条解释字节码指令执行(速度较慢) |
| 即时编译(JIT, Just-In-Time Compilation) | 对“热点代码”(重复调用的方法)进行 动态编译成本地机器码,大幅提升运行速度 |
正是这种执行方式,使得Java可以运行时多态。
Q:一个有main函数的类实例化了另一个有main函数的类,那么调用谁的main?
在.cpp里,一个main函数意味着一个可执行文件,不可能存在可执行文件调用另一个可执行文件,只能依赖操作系统再开一个进程。但是在Java里,却实现了这个,Java 允许多个类都有 public static void main(String[] args) 方法,但是程序执行时只会从你运行的那个类的main方法开始执行,其它的main不会自动调用。目前能想到的优势,大概只有调试比较方便,毕竟在一个封装好的类里加main很奇怪。
变量类型
C++的数据类型包括:基本类型、自定义类型、指针类型、引用类型。你可以指定变量在堆上还是栈上,不使用new的话,默认对象在栈上,而在堆上申请的内存需要手动释放。
在Java里,包括两种变量类型:基本类型和引用类型,除了int这种基本类型外的类、接口、数组、自定义对象(包括 String、List、自定义类等)全是引用类型,只有你new出一个对象才会在堆上分配实际空间。
我们使用代码来说明两者的区别:
Myclass a;
Myclass b = a;
在C++里,上述代码会在栈区创建两个实例,sizeof(a)==sizeof(b)==sizeof(Myclass),也就是说,栈上的就是对象本身,等号进行的是赋值操作(堆操作符=的重写)。但是当Java执行这个语句之后,sizeof(a)==sizeof(b)==4/8字节,可以认为,这只是两个指针,由于没有指向具体的对象实例,所以是空。这里可以看出,Java的引用可以为空,C++不可以。
再看一个代码:
Myclass a = new Myclass();
Myclass *a = new Myclass();
上面的语句是Java在堆上实例化对象,下面语句是C++在堆上实例化对象,a都是储存在栈区的变量,指向堆上的实例。
线程调度的区别?
cpp的线程管理依赖于操作系统的API,而Java由于有自己的虚拟机,所以在操作系统的线程管理上可以再进行一次封装,所以Java通过线程池框架来对线程进行管理。CPP的优势在移动端对性能敏感的业务里更能体现,比如线程绑定核心,安卓移动应用开发使用的是JNI调用底层的C/C++接口。Java线程生命周期有六个状态,在操作系统的线程状态上对等待态进行了划分,分为:阻塞,等待,定时等待。
网络编程
我没有网络编程开发经验。。。。
| 维度 | Java网络编程 | C++网络编程 |
|---|---|---|
| 易用性 | 高(内置库+面向对象封装) | 低(依赖系统API或第三方库) |
| 跨平台 | 统一平台(JVM) | 需适配多平台 |
| 性能 | 较高 | 极高 |
| 内存安全 | 自动管理 | 手动管理,需谨慎 |
| 异步支持 | NIO、AIO | Boost.Asio等异步库 |
| 典型应用 | 企业级应用、服务端 | 高性能服务器、底层系统 |
接口编程 + 多态
cpp的多态通过虚函数实现的,子类重写父类的虚函数来实现多态。而对于Java而言,实现多态有两个机制: 1. 重写父类的成员函数,不需要声明为虚函数或者接口,直接子类前面+@override即可。 2. 直接声明一个接口,而实现它的类必须重写接口。这里需要强调的是,这个接口不是父类,这种实现是重写,而不是继承。接口可以继承,一个接口可以继承另一个接口
父类中的任何函数都可以重写吗?
有限制,以下几种方法不可以重写:
private方法:子类无法访问父类的private方法,自然也无法重写,如果你在子类中写了同名方法,其实是一个新的方法,不是重写。final方法:被final修饰的方法不能被重写,编译器会报错。static方法:静态方法属于类,不属于对象,不能被重写,但可以在子类中定义一个同名的静态方法(这叫“隐藏”,不是重写)。
注意!由于Java的垃圾回收机制,所以不需要析构函数!
模板与泛型
这里体现了JVM存在的优势,cpp编译器编译出可执行文件之后,一切按照可执行文件来运行,而Java则是在编译时擦除类型信息,在运行时由JVM根据对象的类型指针来知道这个对象是什么类型的,进行类型强制转化。而泛型擦除的安全,又编译器负责检查,JVM知道当前代码一定是类型安全的,只需要根据你传入的对象类型,判断实际的类型就可以了。
泛型
Java 编译器在编译时使用泛型进行类型检查和类型推导,但在编译完成后,所有的泛型类型信息都会被“擦除”。例如:
List<String> list = new ArrayList<>();
list.add("hello");
// 编译后的字节码中其实是:
List list = new ArrayList();
list.add("hello"); // 没有泛型类型
泛型类型参数会被擦除为其上界(默认为 Object),如果你写了 ,擦除后就是Number,所有泛型方法、类只会生成一份.class文件。
JVM并不需要知道泛型的类型,它只当作是Object或擦除后的上界类型来处理,依靠的是多态机制(方法分发)和强制类型转换。
模板
C++ 在模板使用时,每用一个类型实例化模板,就生成一个新的代码版本。按需实例化:遇到新类型就生成新函数/类,每个模板参数类型对应一个完整实现,生成的是普通函数/类,与泛型无区别。可以认为是,编译器帮你做了重复性的代码工作,但是在编译时,他们就是不同的类型。
java学习篇(一)—— CPP和Java的区别之基础概念的更多相关文章
- Java 学习(17): Java 泛型
Java 泛型 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说将 ...
- Java 学习(18):Java 序列化& 网络编程& 发送邮件
--Java 序列化 -- 网络编程 -- 发送邮件 Java 序列化 Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据.有关对象的类型的信 ...
- Java 学习(19):Java 多线程编程
Java 多线程编程 Java 给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特 ...
- Java 学习(20):Java Applet 基础 & Java 文档注释
-- Java Applet 基础 -- Java 文档注释 Java Applet 基础 Applet 是一种 Java 程序.它一般运行在支持 Java 的 Web 浏览器内.因为它有完整的 Ja ...
- Java 学习(21):Java 实例
Java 实例 本章节我们将为大家介绍 Java 常用的实例,通过实例学习我们可以更快的掌握 Java 的应用. Java 环境设置实例 //HelloWorld.java 文件 public cla ...
- Java 学习(22):Java MySQL 连接
Java MySQL 连接 本章节我们为大家介绍 Java 如何使用 使用 JDBC 连接 MySQL 数据库. Java 连接 MySQL 需要驱动包,最新版下载地址为:http://dev.mys ...
- 最新java学习路线:含阶段性java视频教程完整版
最新java学习路线:带阶段性java视频教程版本 第一阶段:Java基础 学习目标: 掌握基本语法.面向对象.常用类.正则.集合.Io流.多线程.Nio.网络编程.JDK新特性.函数式编程 知识点细 ...
- Java 学习(1): windows java 运行& 环境配置
Java 文件的运行 如下,创建了一个 名为"HelloWorld.java" 的 Java 文件: public class HelloWorld { public static ...
- Java 学习(2):java 基础概念
Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载 基础语法: 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.以 ...
- Java 学习(3):java 对象和类
目录: --- 对象 --- 类 --- 源文件的声明规则 --- Java 包 对象: 对象是类的一个实例(对象不是找个女朋友),有状态和行为.例如,一条狗是一个对象,它的状态有:颜色.名字.品种: ...
随机推荐
- 🎀dubbo 2.7.2 启动报错【Unsupported generic type false】排查
1.问题现象 dubbo服务启动时抛出异常Unsupported generic type false,但不影响服务正常发布. Caused by: java.lang.IllegalArgument ...
- 为什么 MySQL 选择使用 B+ 树作为索引结构?
为什么 MySQL 选择使用 B+ 树作为索引结构? MySQL 选择 B+ 树作为其索引结构的主要原因是它具有以下几个优势,这些优势使得 B+ 树非常适合用于数据库系统中的索引实现. 1. 高效的范 ...
- windows切换nodejs版本
卸载之前的nodejs 第一步:下载nvm并安装 (推荐使用nvm-setup.zip) https://github.com/coreybutler/nvm-windows/releases 第二步 ...
- 安装debian12和win11双系统
安装环境:微星主板,AMD CPU 5700G 使用rfues制作分别制作win启动盘(可以在i tell you下载)和debian12(清华源下载较快)启动盘 先安装windows: 主板设置U盘 ...
- ArcGIS拼接、镶嵌同一空间位置的不同遥感影像
本文介绍在ArcGIS下属的ArcMap软件中,对处于同一空间位置的多幅栅格图像加以拼接.融合与叠加等操作的方法. 假如现在我们分别有以下三幅栅格图像,三者分别是独立的三个图层.第一个图层如下 ...
- Docker自定义镜像输出日志
概述 本文主要解决Docker自定义镜像之后,通过docker logs命令查看不到相关日志的问题 在 Docker 中自定义镜像输出日志,通常需要确保你的应用程序将日志输出到 标准输出(stdout ...
- 企业级分布式MCP方案
飞书原文档链接地址:https://ik3te1knhq.feishu.cn/wiki/D8kSwC9tFi61CMkRdd8cMxNTnpg 企业级分布式 MCP 方案 背景:现阶段 MCP Cli ...
- HttpServletResponse相关
目录 返回给客户端数据:字节流和字符流 解决返回字节流和字符流乱码问题 万能解决乱码 文件下载 tomcat提供的默认下载方式 手动编写的DownloadServlet 返回给客户端数据:字节流和字符 ...
- django笔记(3)-数据库操作
一:路由系统 url 1.url(r'^index/', views.index),url(r'^home/',views.Home.as_view()), 一个url对应一个函数或一个类 ...
- SQL 日常练习 (十八)
也没啥, 就是入坑 sql 根本停不下来, 势必要达到所谓 "精通" 的地步. 从网上的例子也快搬运完了, 而工作中的 sql 又是万万不能外泄了. 因此想着, 该去哪里搬砖呢, ...