×

泛型擦除

究竟是.Net好还是Java好,欢迎大家发言,畅所欲言?Java和C# 哪个语法上更简单在校生应该选择学习哪个

admin admin 发表于2023-02-10 16:37:05 浏览50 评论0

抢沙发发表评论

本文目录

究竟是.Net好还是Java好,欢迎大家发言,畅所欲言

现在流行的语言,java是最烂的。

对于从C#转过来的我来说尤其如此。在一个java项目告一段落之际,现在让我吐槽一下:

1. java的泛型让人费解。类型擦除让泛型的优势荡然无存。本来泛型的一大优势是避免装拆箱的性能开销。在java里,仅仅就剩下语法糖的功能。况且这颗糖非常的不好吃。

2. java里的lambda表达式实在是难看得要死。本来业界都用=》来代表箭头函数,java非要用-》显得和别人不同。这也就算了,凡用到lambda的地方还非要steam()转一下,对于数组,还要Array.stream(), 要多别扭就有多别扭,要多难看就有多难看。更坑爹的是,还不支持延迟加载,用过一次再接着用就报错!

3. java的方法的异常处理声明让人恼火。我们知道,现在AOP编程,异常都是在框架上层集中处理的。底层只管抛就是了。一般情况下,不主张在底层用catch“吃掉”异常. 这就导致,如果我不想吃掉异常,就得抛出,如果要抛出,就得在方法声明后加throws xxxException。而如果一个方法调了其他的方法,也要跟着throws 这个Exception, 如果调了n多有异常的方法就得throws n多个Exception. 当然有人会说,你不会只throws 单一的基类Exception吗?这样倒是可以简单点。 那这个throws机制还有什么用呢?

4. java没有随用随丢的匿名对象,类似C#的new { a, b}, 或者像js那样更简单的{a, b}。这在传给api传参时,或者webapi返回的结果,是由几个值组成,但又不值得定义一个类时,显得特别啰嗦,导致我要么用一个hashmap来装,要么再专门定义一个只用一次的类。

5. java没有var的隐式类型声明。接受一个很长的类型名的返回结果时,特别不简洁。这个据说在java12以后支持。但是现在谁敢用java8以上的版本?

6. java没有扩展方法的机制。导致现在java的Util类满天飞。你如果想想像别的语言那样,一气点下去,简直是作梦。你不得不在写好一个对象以后,发现它没有你要的方法,然后不停把光标调到对象前面,加util,再加括号,再移到对象后面,再加反括号。太不顺畅了!

7. 现在流行的spring-boot实在是太慢了。我写一个单元测试,运行一次,初始化都要一分钟,搞得我现在烟抽得越来越多!

当我,我才写两个月的java代码,难免对java有所偏见。欢迎各位java大神拍砖!

------分割一下------

我看有很多的java大神在喷我,评论比点赞还多,我说一下 我没有很极端,有些问题确实不及别的语言优秀,我既然学它 肯定还是一门好的语言。

C++之父Bjarne Stroustrup说过:世界上只有两种编程语言,一种是整天被人骂的,还有一种是没人用的。

Java和C# 哪个语法上更简单在校生应该选择学习哪个

程序员入门的第一个程序都是Hello World!

java

System.out.println(“Hello World!“);

C#

System.Console.WriteLine(“Hello World!“);

有没有发现两者真的很像,一个熟悉C#的人去写java程序其实不难,反之亦然!

相比较而言java的市场环境比c#要大很多,尤其在互联网领域,移动端领域几乎不可代替!

C#在工控领域用的比较多,当然在游戏领域基于Unity3d + C# 开发了大名鼎鼎的王者荣耀

其实对于学校学生来讲,我倒是建议先学好C或是C++这些基本语言,因为底层的算法只有当你一个个实现了之后你才能理解当中的原理和奥妙!

C# 随便引入一个namespace, java import 一个package 都能够快速的实现相关应用,也就是说你只会用,不知道为什么这么用?对于后期工作了你想往更高层次走比较难!

应用层会使用尤其对学生来讲不应该被倡导!

我觉得大学生应该知其然并知其所以然!

我面试过很多学生,只要基础功底扎实,不管是学什么语言的都能够在转化语言过程中很快上手!

我们部门有学java,c#,Python等出身的,基本上各个语言差不多都能轻松应对!

我还是重申一下学生不应该说学哪个简单?

而是学哪个更有市场就学哪个,因为你必须面对就业!

我的建议先学好C/C++再去学java/C#

Java为什么要有泛型

java里的泛型是奇葩的存在。这也是我经常怼java的一个原因。

先说下泛型的主要作用:

1,强化类型安全,比如定义了一个List<String>,那么里面只能存放String,不允许存放其他类型(派生自String的除外)。类型安全应该在编译和运行时都能体现。

2,提高性能,减少类型转换和装箱拆箱次数。

再说下java泛型奇葩之处:

1,java泛型实现的原理叫类型擦除,不管代码中怎么定义泛型,编译后都变成object, 因此不能实现运行时的类型安全。 而且java编译器不够聪明,可以很容易骗过去。 举个例子,你调用了第三方的接口返回List<String>,但实际拿到的值里面可能跟String没有半毛钱关系。

2,既然类型被擦除,那么类型转换就不可避免了,因此使用泛型和非泛型在性能上没有任何变化。

Java和C# 最大的不同是什么

我觉得抛开语法而谈,最主要的还是对底层的控制能力不同。

C# 一开始虽然借鉴 Java,但是目的完全不是为了造一个 better Java,而是造一个 better C++。游戏引擎们偏爱 C# 也是有这一层原因在里面。

比如在 C# 里面你能干的:

上述代码会输出 10,为什么?因为 .NET 中数组的长度存储于数组第一个元素之前的 8 字节内存中。如果你再接着输出 *((long*)p - 2),将会直接得到这个对象的 TypeHandle 地址:

然后拿着这个指针又接着能去访问对象的 MethodTable。

再有你还可以手动在栈上分配空间:

接着你想绕过 GC 直接手动分配堆内存:

上述调用等价于你在 C 语言中调用的 malloc,此外还有 AllocAligned、Realloc、AllocZeroed 等等,可以直接控制内存对齐。

接下来你想创建一个显式内存布局的结构 Foo:

然后你就成功模拟出了一个 C 的 Union,之所以会有上面的输出,是因为单精度浮点数 1 的二进制表示为 0x00111111100000000000000000000000,以小端方式存储后占 4 个字节,分别是 0x00000000、0x00000000、0x10000000、0x00111111。

进一步,你还能直接从内存数据没有任何拷贝开销地构造对象:

甚至这样:

从堆内存创建自然也没问题:

再比如,此时你面前有一个使用 C++ 编写的库,其中有这么一段代码:

然后我们编写如下 C# 代码:

上面的代码干了什么事情?我们将 C# 的函数指针传到了 C++ 代码中,然后在 C++ 侧调用 C# 函数生成了一个字符串 wwwww,然后将这个字符串返回给 C# 侧。而就算不用函数指针换成使用委托也没有区别,因为 .NET 中的委托下面就是函数指针。

甚至,如果我们不想让 .NET 导入 foo.dll,我们想自行决定动态库的生命周期,还可以这么写:

上面这些都不是 Windows 专用,在 Linux、macOS 上导入 .so 和 .dylib 都完全不在话下。

再有,我们有一些数据想要进行计算,但是我们想使用 SIMD 进行处理,那只需要这么写:

可以看看在 X86 平台上生成了什么代码:

平台判断的分支会被 JIT 自动消除。但其实除了手动编写 SIMD 代码之外,前两个分支完全可以不写,而只留下:

因为现阶段当循环边界条件是向量长度时,.NET 会自动为我们做向量化并展开循环。

那么继续,我们还有ref、in、out来做引用传递。

假设我们有一个很大的 struct,我们为了避免传递时发生拷贝,可以直接用 in 来做只读引用传递:

而对于小的 struct,.NET 有专门的优化帮我们彻底消除掉内存分配,完全将 struct 放在寄存器中,例如如下代码:

上述代码 GetDistance 考虑是个热点路径,因此我加 MethodImplOptions.AggressiveInlining 来指导 JIT 有保证地内联此函数,最后为 Test 生成了如下的代码:

全程没有一句指令访存,非常的高效。

我们还可以借用 ref 的引用语义来做原地更新:

甚至还能搭配指针和手动分配内存来使用:

C# 的泛型不像 Java 采用擦除,而是真真正正会对所有的类型参数特化代码(尽管对于引用类型会共享实现采用运行时分发),这也就意味着能最大程度确保性能,并且对应的类型拥有根据类型参数大小不同而特化的内存布局。还是上面那个 Point 的例子,我们将下面的数据 int 换成泛型参数 T,并做值类型数字的泛型约束:

无论是 Test1 还是 Test2,生成的代码都非常优秀,不仅不存在任何的装箱拆箱,甚至没有任何的访存操作:

接着讲,我们有时候为了高性能想要临时暂停 GC 的回收,只需要简单的一句:

就能告诉 GC 如果还能分配 128mb 内存那就不要做回收了,然后一段时间内以后的代码我们尽管在这个预算内分配内存,任何 GC 都不会发生。甚至还能阻止在内存不够分配的情况下进行阻塞式 Full GC:

代码执行完了,最后的时候调用一句:

即可恢复 GC 行为。

除此之外,我们还能在运行时指定 GC 的模式来最大化性能:

更进一步,我们甚至可以直接将堆内存中的代码执行,在 .NET 上自己造一个 JIT,直接从内存创建一块可执行的区域然后往里面塞一段代码用来将两个32位整数相加:

除此之外,C# 还有更多数不清的底层写法来和操作系统交互,甚至利用 C# 的编译器取消链接到自己的标准库,直接用从 0 开始造基础类型然后通过 NativeAOT 编译出完全无 GC、能够在裸机硬件上执行引导系统的 EFI 固件都是没有问题的,参考

怎么样才能学好java编程

不扯那些虚的,要来就来实质性的干货。

明确自己学习的原因

  • 问问自己是抱着什么目的要学习Java,没有目标的学习是效率极低的,并且容易半途而废;

  • 了解Java可以做什么,Java可以从事的岗位以及软件行业的发展情况;

  • 自己是否对Java方向感兴趣;

Java基础

学习准备

  • 推荐看视频入门,可以通过某宝以及某鱼购买相关的视频,别挑三拣四,选中一个视频看完再说,对于初学者,无论选哪一个都是值得你学习的。可以选择传智、黑马、尚学堂等教学视频,买一个系列的即可;

  • 有人说器等IDE环境不适合看视频,浪费时间,但是初学者在学习第一个编程IDE时,推荐看视频或者通过搜索引擎了解工具的使用,看书其实在刚开始可能更浪费时间;

  • 看完基础视频对知识有个大概的了解,这时候看书就不会一头雾水,此时可以通过看书来深入学习,之后的学习可以自己选择看书还是看视频,最好的方法是花时间既看视频也看书;

  • 学着学着忘掉前面的别总想着回头记住,先往后学,有些基础知识暂时用不上,当你学到应用的知识时自然会慢慢理解;

书籍推荐

入门书籍:《Head First Java》、《Java 核心技术》

进阶书籍:《Java编程思想》

Java Web

学习完Java基础,接着适合学习Java Web,这个推荐看视频,学习数据库和JDBC基础知识以及基本的前端知识,然后学习SSM框架,学习路线为:

Mysql -》 JDBC -》 HTML、CSS、JavaScript、JSP -》 Spring -》 SpringMVC -》 Mybatis -》 SSM整合 -》 SSM项目实战

推荐两本书:

《深入分析 java web 技术内幕》

《架构探险-从零开始写java web框架》:讲解 ioc、aop 通俗易懂,实现 ioc、aop

实战之后返回深入学习 Java 相关知识,自顶向下学习,通过大概学习基础,实战之后返回深入学习基础知识,由广至深。

并发编程

推荐书籍:

《Java并发编程的艺术》

设计模式

《Head First 设计模式》

JVM

《深入理解 Java 虚拟机》

要想超越别人,不仅仅要掌握实战技能,更重要的是基础扎实


算法

《算法》第4版

计算机网络

《图解TCP/IP》

《图解HTTP》

操作系统

《操作系统概念》(恐龙书)

这么多已经够你学习了,主要是行动起来,还有更深入的,比如数据库方面以及Java相关的方面,等你学完以上知识相信你自己已经知道需要学习什么了,不要一次被这么多内容吓到,只要静下心来,下一个大神就是你。


附上一张可供参考的详细思维导图

我听很多人说JAVA已经过时了,下一个要淘汰的语言就是JAVA,真的是这样吗

先说结论:Java正在过时,并且可能会被淘汰。

每次有人唱衰Java的时候,都会有一群Java程序员愤怒地出来反驳,我也曾是其中的一员。但是现在我更喜欢尊重事实,拿数据说话。

TIOBE编程语言社区指数

从TIOBE网站每月提供的编程社区指数,我们可以清晰地看到,Java的占比从2001年6月的26.49%逐渐减少到今年(2021)6月的11.54%,20年间下降了15%。这个排行榜是根据互联网上有经验的程序员、课程和第三方厂商的数量,并根据各大搜索引擎的搜索热度以及Wikipedia、Amazon、YouTube统计出的排名数据,可以说能够客观反应出各编程语言的热门程度。因此,我们可以得出结论:Java正在逐渐走向衰落。

下面我将试着分析Java市场份额逐渐减少的原因,以及Java语言的优缺点,希望能对你有所帮助。

Java占比减少的原因:

  1. 各种新语言的崛起。Java鼎盛的时候,市场的竞争对手很少。而这些年,随着计算机硬件的发展以及互联网的普及,各种编程语言也随之井喷式地出现。每种相对热门语言出现和发展都会吸走一部分热度,并带起新的一波唱衰Java的节奏。这些语言的代表早期有C#,最近有Go。
  2. JVM体系中一些“Better Java”的出现。由于Java语言本身的一些弊病(下文会详细说),JVM上出现了一些语言,如Scala、Groovy、Kotlin,它们打着“Better Java”的旗号,采用和Java互通的形式发展。一些对Java体验不满的团队,可能会选择转向这些语言。
  3. 互联网热点的切换。前些年服务器端编程可能是互联网领域的主流,近年来由于机器学习、大数据等概念的兴起,对这些概念支持更好的语言得以兴起,如python、R、Scala等。
  4. Java语言自身的缺陷。

Java语言的缺陷:

  1. 语言特性不够丰富。Java具有跨平台和向下兼容这两大卖点,但它们同时也是Java语言沉重的包袱。带着这些包袱,Java只能缓慢保守地增加语言特性。一些其他成熟语言具备的特性,Java只能选择不支持或通过替代的方式支持。如Java中没有函数的数据类型,使用“类型擦除”的方式实现泛型等。
  2. 语法过于啰嗦。Java的样板代码可能是所有编程语言里最多的。Python程序员100行代码可以搞定的事情,Java程序员可能要写上500行代码。
  3. 应用场景不是刚需。Java虽然在服务器编程方面找到了统治地位,但是这种统治地位并不牢固。具有服务器编程能力的语言太多了,如php、python、Go、dart等,甚至js这种浏览器端的语言也来凑个热闹,搞了node.js专门用于服务端编程。
  4. 对多线程的支持不友好。Java对多线程的支持设计得非常不友好,即使经验丰富的程序员,也容易编写出产生致命缺陷的代码。

Java语言的优势:

  1. 上手简单。Java的语法少,并且非常符合直觉,非常适合作为新人的入门语言。
  2. 生态完整,社区活跃。有海量的第三方框架和依赖包,基本上各个领域都能找到成熟的解决方案。
  3. 跨平台。对各个平台的支持比较完善,基本可以实现“一次编写,到处运行”。
  4. 存量项目多。Java运行在数以亿计的硬件设备上,这些系统的维护工作足以养活一大批Java开发的程序员。

Java程序员何去何从?

  1. 首先不要过分焦虑,Java被淘汰不会是一两天的事情。
  2. 其次不要把鸡蛋放在一个篮子里,多掌握一些技术,技多不压身。
  3. 最后提高对自己的要求,多修炼内功,从原理上理解编程,这样就可以不受语言的限制,随时能够适应新的领域的工作。