3. 技术专题 - 编程语言的演化、对比
- 基本语法
Java | C# | C++ | Typescript | |
---|---|---|---|---|
基本数据类型(值类型) | boolean, byte, short, int, long, float, double, char | bool, sbyte, short, int, long, byte, unshort, uint, ulong, float, double, decimal, char | boolean, number | |
包装类(Java中是引用类型) | Boolean, Byte, Short, Integer, Long, Float, Double, Character | Boolean, SByte, Int16, Int32, Int64, Byte, Double, Decimal, Char | ||
数据类型(引用类型) | String, Object, 数组 | string/String, Object, dynamic | string, Array<T>/T[] | |
模块组织 | package + import | namespace + using | import | |
继承 | extends | : | :[继承方式] [基类名] | extends |
实现 | implements | : | :[继承方式] [接口名] | implements |
变量定义 | let, const | |||
变量性质 | static, readonly |
-
包装类
- Java
- 包装类都继承自Number,而Number继承自Object,Java万物皆对象
- 8个包装类和8个基本数据类型一一对应
- 基本数据类型并不是对象,所以Java不是纯面向对象的语言
- Java的范型在编译后实际上变成Object(类型擦除),范型中只能使用包装类?
- 开发中要避免不自觉的拆装箱,避免性能消耗。一般情况下多使用基本数据类型。
- 操作
- new Integer(int value)、new Integer(String s)等构造函数
- compareTo(T o):来自public interface Comparable<T>,返回值是int
- public static Integer valueOf(String s)、valueOf(int i)等多种入参列表的初始化函数
- public static int parseInt(String s):多种入参列表的字符串转换成类型的函数
- intValue()、doubleValue()等获取基本数据类型的转换函数
- public static int max(int a, int b)等专有操作
- toString(int i)等多种入参列表的序列化函数
- 等等
- C#
- C#中基本类型其实就是包装类,一样的!
- C#类型和CLR类型
- 接上面的结论,既然都一样,为什么还要提供Int32这种呢?这是因为.Net Framework是一个基础平台,它要支持建立在此基础上的各种语言,以及跨语言程序之间的通信。因此.Net Framework对外提供的资源必须是通用的,并且避免使用某种语言的特有称呼,以免造成不必要的混淆。所以System.Int32是.Net Framework对32位整数的标识,MSDN对这种类型标示的称呼是User Type。而int则是c#语言里面的特有称呼(这里它对应的.Net Framework里的System.Int32),MSDN对c#的int的称呼是Keyword。int就是System.Int32的别名而已!
- 当然,int在32位机器和64位机器上是不同的,而Int32都会是32位的
- 基本数据类型和包装类都是struct
- 和Java相比
- 所谓的基本数据类型其实和CLR封装类类型是一样的,是同样的struct,有点像是语法糖,并不像Java那样是真正的基本数据类型
- 区分了有符号、无符号数;
- 多了decimal和Decimal;
- Double包装类型同时相应代表了float和double;
- 包装类中用CLR类型中的Int16、Int32、Int64相应代表了基本数据类型中的short、int、long、unshort、uint、ulong等数字类型。
- 操作
- 由于基本数据类型和CLR包装类型其实是相同的struct,因此和Java不同,没有构造函数。
- CompareTo(Int32 value):来自public interface IComparable,返回值是int
- public static Int32 Parse(string s)等多种入参列表的转换函数
- public static bool TryParse(string s, out Int32 result)等多种入参列表的转换函数(不会抛出异常)
- ToString(string format)等多种入参列表的序列化函数
- public const Int32 MaxValue = 2147483647;
- public const Int32 MinValue = --2147483648;
- 等等
- Java
-
高级特性
Java C# C++ Typescript Python 可空类型 Optional<T> - 1.8以上 T?, Nullable<T> 无 无 类型判断 instanceof is 类型转换 as, (<T>var) 自动推断类型 var auto - 11以上 any 动态类型 dynamic 无 重命名类型名 using typedef 模版字符串/字符串插值 无原生实现? $"{name}" '${name}' - 可空类型
- Java - Optional
- 初始化
- (必须传入非null值)Optional<T> java.util.Optional.ofNullable(T value)
- (可传入null值)Optional<T> java.util.Optional.of(T value)
- (获取一个初始的空值)<Object> Optional<Object> java.util.Optional.empty()
- 判断是否真的有值:boolean java.util.Optional.isPresent()
- 获取值:T java.util.Optional.get()
- T java.util.Optional.orElse(T other)
- <U> Optional<U> java.util.Optional.map(Function<? super PlantDataSource, ? extends U> mapper)
- C# - ?, Nullable
- 初始化
- (推荐)T? xxx = yyy;
- (不推荐)Nullable<T> xxx = yyy;
- 判断是否真的有值:bool Nullable
.HasValue - 获取值:T Nullable<T>.Value
- 获取值(或默认值):T Nullable<T>.GetValueOrDefault()
- 获取值(或默认值,提供了默认值):T Nullable<T>.GetValueOrDefault(T defaultValue)
- 初始化
- 初始化
- Java - Optional
- 泛型类型约束
- C#
- 接口约束
- public class MyGenericClass<T> where T:IComparable
- 基类约束
- class MyClassy<T, U> where T : class where U : struct
- 接口约束
- C#
- 可空类型
-
其他
- new的同时为部分成员变量赋值
- C#
- Contact = new OpenApiContact
- C#
- new的同时为部分成员变量赋值
-
参考《码农翻身》
- 不同的语言一定要在擅长的领域做擅长的事,否则就是同一种语言了,各有优劣,适用场景不同。
- C
- 实现的是代码可移植
- 在编译器,需要通过链接把主程序和被引用的程序联系起来(地址映射)
- 不适合入门,成就感较低,但能帮助理解底层运行机制
- VB和Visual FoxPro
- 本地的数据库应用,被淘汰了,不实用
- C++
- 复杂,投入太多,容易出错
- Java
- 实现的是代码和部署都可移植
- 其实也做了链接,只不过是动态链接
- 简单,资源丰富,社区活跃
- Ruby
- 包含Web开发的一些最佳实践,有点像sql那样的DSL
- 但有动态语言的缺点,过于灵活,容易出错(如变量类型,运行时才出现),需要完善的单元测试
- JavaScript
- 最开始叫LiveScript,为了和Java套近乎。。。
- 解释性,避免每个页面都要像C、Java那样编译一下,太慢了
- 一开始只是为了不要所有事都和服务端交互(太慢),在客户端可以做一些事情(操作DOM等),后来有了AJAX(基于XMLHttpRequest,可以异步局部更新了)、JSON(XML太臃肿)后才流行起来,引起了革命性的Web 2.0
- Node.js
- 为了让JavaScript不再依赖于浏览器,将JavaScript引擎搬到了服务器端,可以进行文件、数据库等操作。
- 实现了前后端语言的一致。
- 有了Chrome V8引擎后才真正提高了效率,因为Node.js并不为每个HTTP请求分配一个全程服务的线程(Java后来是不是也不这样了?),而是通过基于事件编程和异步来实现用一个线程服务所有请求,只是要区分出哪些是马上就是处理完的命令,哪些是需要等待的(做成异步回调的,基于事件触发)
- 命令式编程与声明式编程
- 最底层后都是一样的底层代码,是命令式编程还是声明式编程,是针对编程语言的使用者的感受来说的
- 命令式编程
- 需要编程语言使用者一步步指明所有的细节,比如不用sql查询数据库,那么就要拿出所有数据,然后一点点过滤、组合
- 声明式编程
- 8以后也部分支持了声明式编程(Lambda表达式)
- sql就是典型的声明式编程