null何错之有?对于Java程序员而言,NullPointerException是最令我们头疼的异常,没有之一,大明哥相信到这篇文章为止一定还有不少人在写下面这段代码:if(obj!=null){//...}NullPointerException是Java1.0版本引入的,引入它的主要目的是为了提供一种机制来处理Java程序中的空引用错误。空引用(NullReference)是一个与空指针类似的概念,是一个已宣告但其并未引用到一个有效对象的变量。它是伟大的计算机科学家TonyHoare早在1965年发明的,最初作为编程语言ALGOLW的一部分。嗯,就是这位老爷子1965年,老爷子TonyH
Java接口我相信所有学过Java的人一定都知道,而且我也相信99%的人一定都背过这个面试题:Java接口和抽象类的区别是什么?答案都是什么接口方法不能有实现,都是抽象的,接口的方法都默认为public修饰等等之类的,这些在Java8之前是正确的,但是随着Java的发展,它不再是正确的了。这篇文章就跟着大明哥一起来探索Java接口的进化之路。出生:Java1.0引入接口Java1.0,作为Java语言的最初版本,于1996年发布。在这个版本中,Java引入了接口(Interface)这一概念,标志着面向对象编程(OOP)在Java中的深入应用。在Java1.0中,接口被定义为完全抽象的,它具备
Java现在发布的版本很快,每年两个,但是真正会被大规模使用的是3年一个的LTS版本。每3年发布一个LTS(Long-TermSupport),长期维护版本。意味着只有Java8,Java11,Java17,Java21才可能被大规模使用。每年发布两个正式版本,分别是3月份和9月份。在Java版本中,一个特性的发布都会经历孵化阶段、预览阶段和正式版本。其中孵化和预览可能会跨越多个Java版本。所以大明哥在介绍Java新特性时采用如下这种策略:每个版本的新特性,大明哥都会做一个简单的概述。单独出文介绍跟编码相关的新特性,一些如JVM、性能优化的新特性不单独出文介绍。孵化阶段的新特性不出文介绍。首
Java21,发布于2023-09-19。JEP430:字符串模板(预览)字符串的拼接和格式化是我们日常比较常见的一种操作,我们一般有如下几种解决方法:使用+来拼接使用StringBuffer和SpringBuilder来拼接字符串使用String::format和String::formatted来格式化字符串使用java.text.MessageFormat格式化字符串这几种传统的方式都比较麻烦,过程有很繁琐,比如:intx=20;inty=3;,如何输出20+3=21?:Strings=x+"+"+y+"="+(x+y);或者newStringBu
Java19,于2022-09-20发布JEP405:Record模式(预览)Java14引入预览特性Record旨在提供一种简洁的语法来声明类似数据的小型不可变对象,主要是为了解决长期以来在Java中定义纯数据载体类时,代码过于繁琐的问题。在Java16中转为正式特性。instanceof模式匹配也是在Java14作为预览特性引入的,主要是为了解决instanceof在做类型匹配时需要进行强制类型转换而导致的代码冗余。Java19引入Record模式作为预览特性,它允许在instanceof操作中使用记录模式,直接解构和匹配记录中的字段。比如有一个记录RecordPoint(intx,int
引言Java初学者你的第一个Class类一定是下面这个:publicclassHelloWorld{publicstaticvoidmain(String[]args){System.out.println("Hello,World!");}}这个方法对老手来说这个类非常简单,但是对于新手而言,这个类就比较复杂了,因为涉及到了Java里面好几个概念,大明哥给你拆解下:publicclassHelloWorldpublic:这是一个访问修饰符,表示这个类对所有类都是可见的。class:这是一个关键字,用来定义一个类。HelloWorld:这是类的名称。publicstatic
该特性非常简单,就一句话:如果一个变量你用不到,那就用_代替它吧。这个特性的主要目的是提高代码的可读性和可维护性。try{}catch(Exceptione){thrownewRuntimeException("系统蹦啦!!!!");}这段代码熟悉吧。这里的e就是一个没有使用的变量,按照这个特性,我们可以用_代替。try{}catch(Exception_){thrownewRuntimeException("系统蹦啦!!!!");}这个特性使用的场景还是比较多的,比如for循环:List<String>list=List.of("
引言字符串操作是Java中使用最频繁的操作,没有之一。其中非常常见的操作之一就是对字符串的组织,由于常见所以就衍生了多种方案。比如我们要实现x+y=?,方案有如下几种使用+进行字符串拼接Strings=x+"+"+y+"="+(x+y);使用StringBuilderStrings=newStringBuilder().append(x).append("+").append(y).append("=").append(x+y).toString()String::format和String::formatted将
我们先看在Java21之前,访问Java中集合的第一个和最后一个元素的方式:集合获取第一个元素获取最后一个元素Listlist.get(0)list.get(list.size()-1)Dequedeque.getFirst()deque.getLast()SortedSetsortedSet.first()sortedSet.last()三个集合提供了三类不同的使用方法,非常混乱。为了解决这种混乱,Java21引入有序集合,旨在解决访问Java中各种集合类型的第一个和最后一个元素需要非统一且麻烦处理场景。它新增了SequencedCollection,SequencedSet,Sequenc
Java20,于2023-03-21日发布。JEP429:作用域值(第一次孵化)在多线程环境下,正确管理上下文数据是一项有挑战的事情,传统的解决方案(如ThreadLocal)在某些场景下并不是很适用或者效率比较低下。Java20引入作用域值(ScopedValues),它可以在线程内和线程间共享不可变的数据,并且优于线程局部变量。ScopedValues是一种新的机制,它主要用于在线程或虚拟线程中安全地传递和访问数据,它允许在代码的不同部分之间传递信息,例如,在多线程应用中从父线程向子线程传递数据。它的引入解决了两个问题:线程局部存储的限制:ThreadLocal可能会导致内存泄漏,并且不适
Record是Java14引入的,它主要目的是提供一种简洁的语法来声明类似数据的小型不可变对象,主要是为了解决长期以来在Java中定义纯数据载体类时,代码过于繁琐的问题。它的本质上是一个不可变的、透明的数据载体对象,我们可以理解它是一种特殊类型的Java类。定义Record方法如下:publicrecordUser(Stringname,Integerage){}Record会自带getters、equals()、hashCode()和toString()方法,无需我们手写。但是我们在使用类型匹配时仍然需要强制转换下,如下:publicvoidrecordTest(Objectobj){if(
很多语言都有类似于“虚拟线程”的技术,比如Go、C#、Erlang、Lua等,他们称之为“协程”。曾经我们Java开发者面对这种平凡而又高级的技术只能干瞪眼,然而现在我们JavaBoy也能挺起腰杆子说:协程算个の。为什么引入虚拟线程小明同学作为一个初入职场的小菜鸟,某天接到老板的任务,要他写一个简单的需求:前端传一个fileId过来,需要去文件服务器下载下来并解析,然后针对解析的内容做一些xxx的事情,需求很简单,小明哥三下五除二就搞定了:publicvoiddoSomething(StringfileId){StringfilePath=downloadFile(Field);List<
Java18,于2022年3月发布。JEP400:默认UTF-8编码在Java18之前,Java的标准字符集(Charset)是根据操作系统的区域设置决定的。这意味着在不同的操作系统和区域设置下,Java程序的行为可能会不同,特别是在处理文本数据时。这种不一致性导致了许多问题,尤其是在跨平台部署和国际化应用程序时。而且UTF-8支持几乎所有语言的字符。所以Java18将UTF-8设为Java平台的默认字符集,解决了跨平台的一致性问题。从此以后,Java在处理文本数据时的行为在各种平台上就更加一致,减少了与字符编码相关的错误和混淆。JEP408:简易Web服务器Java18引入该特性的主要目的为
Java17,发布于2021年9月,是一个长期支持(LTS)版本。JEP356**:**增强型伪随机数生成器在Java17之前,Java的伪随机数生成主要依赖于java.util.Random类及其子类,如ThreadLocalRandom和SecureRandom。这些类虽然功能强大,但在某些特定应用场景中存在局限性,如需要特定类型的随机数生成器(例如具有更长周期的生成器),或需要更细粒度的控制和更广泛的算法选择。Java17引入增强的伪随机数生成器其目的是在Java标准库中引入更多种类的随机数生成器,并提供一种更为统一且易于使用的方式来访问和使用这些生成器。它的主要内容包括:新的接口和实现
随机数,这个没有小伙伴没有用过吧,Java提供了几个用于生成随机数的类,他们使用起来是这么地简单,以至于我们很少去认真的对待随机数的具体结果,就好像它是真的随机一样。Java17之前的伪随机数生成器在Java17之前,Java的随机数生成主要依赖于下面两个核心类:java.util.Randomjava.security.SecureRandomRandom该类是最最基本的伪随机数生成器,它用于生成一系列不完全是真正随机的数字。Random提供了多种方法来生成不同类型的随机数,包括整数、长整数、浮点数等。生成随机整数Randomrand=newRandom();intrandomInt=ran
Switch表达式Java12引入Switch表达式,它解决了传统Switch语句的两个缺陷:"Fall-through"行为:在没有显式break语句的情况下,Switch语句会从一个case"穿透"到下一个case,忽略了这个会导致不可饶恕的错误。代码冗余:每个case,我们都需要重复类似的代码结构,增加了代码的冗余和维护难度。Switch表达式引入了->操作符,用于替代传统的冒号(:)。与传统的Switch语句不同,使用->的case分支不会出现"fall-through"现象,因此不需要break语句来防止穿透,如
Java16在2021年3月16号发布。JEP338:向量API(孵化器)在现代计算中,数据密集型操作是非常常见的,例如科学计算、机器学习、图形处理等等,这些操作往往可以通过向量化来加速(即同时对多个数据项执行相同的操作)。但是,Java缺乏一种官方的、标准的方式来利用硬件的向量计算能力,这就限制了Java在处理这类操作时的性能。Java16引入向量API来填补这一空缺。向量API提供了一套用于表达向量计算的API,可以在支持SIMD(单指令多数据)的处理器上运行。它使得Java能够更有效地利用现代处理器的向量计算能力,从而提高性能。API设计为平台无关,但可以在支持的硬件上利用特定的优化。J
Java15在2020年9月15号正式发布。JEP339:Edwards-Curve数字签名算法(EdDSA)在数字签名算法领域,安全性始终是首要考虑的因素,但是随着技术的发展,一些旧的签名算法(如RSA和ECDSA)面临着越来越多的安全挑战。EdDSA是一种更加现代换的签名算法,相比于传统算法,它提供了更强的安全性。同时,在同等安全级别下,EdDSA通常比ECDSA等算法更快,特别是在签名生成和验证过程中,这就意味着对于需要处理大量数字签名的系统,EdDSA可以显著提升效率。Edwards-Curve数字签名算法(EdDSA),一种根据RFC8032规范所描述的Edwards-Curve数字
Java14是一个非LTS版本,发布于2020年3月17日。JEP361:Switch表达式(正式特性)Java12引入Switch表达式作为预览功能发布,Java13对其进行增强处理。在Java14中,switch表达式已经是一个标准特性。Switch表达式主要功能包括:简化的语法:switch表达式允许使用更简洁的箭头语法(->),这样可以直接返回一个值,而不需要break语句。多值匹配:在一个case分支中,可以同时匹配多个值,使用逗号分隔。yield**关键字**:当使用传统的switch块语法时,可以使用yield来返回一个值。Java版本更新类型JEP更新内容Java12预览
什么是隐藏类隐藏类,是一种不能被其他类直接使用的类。Java15引入隐藏类主要针对的是库和框架的开发者,而不是直接面向普通Java应用程序开发者。它有如下几个特点:不可见性:隐藏类对于Java的反射API是不可见的,这意味着它们不能通过正常的反射机制被发现或访问。但是,这并不是说,他们是完全不可见的,我们需要知道访问他们的“密码”,只要知道这个密码就可以访问他们。隐藏类与普通Java类的最大区别就是隐藏类并不是“广而告之”的,需要通过特殊的手段来找到他们。不兼容性:隐藏类与普通的Java类不兼容,这意味着我们不能将一个隐藏类实例转换为任何非隐藏类,也不能将非隐藏类转换为隐藏类。生命周期管理:隐
引言继承,作为面向对象语言的三大特性之一,我相信没有小伙伴不知道吧?在工作过程中我们也经常使用继承,我么知道子类继承父类,可以重写父类的方法,编写自己独特的属性与行为,任何依赖父类的业务,子类都可以替换掉它。这种情况再绝大多数情况下是非常有价值的,除了少数情况。这少数情况就是:我们需要继承,但是我们又期望能够限制它继承的能力。是不是很矛盾?我们以加密算法为样例来说明。我们知道在加密算法的设计中,确保算法的实现不被随意修改或扩展是至关重要的。加入你负责一个内部通信框架,报文都需要加解密。你设计了一套通用的加密算法,其中包含几种标准的加密算法,如AES、DES和RSA,如下:publicabstr
我们定义如下两个类:@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{privateStringuserName;privateAddressaddress;}@Data@NoArgsConstructor@AllArgsConstructorpublicclassAddress{privateStringprovince;privateStringcity;}写个测试类测试下:publicclassTest{publicstaticvoidmain(String[]args){Useruser=newUser();System
为什么要引入Record我相信很多小伙伴对下面的代码一定非常熟悉:publicclassUserDTO{privateStringuserName;privateIntegerage;publicUserDTO(StringuserName,Integerage){this.userName=userName;this.age=age;}publicStringgetUserName(){returnuserName;}publicvoidsetUserName(StringuserName){this.userName=userName;}publicIntegergetAge(){retu
instanceof是Java中的一个关键字,它用于检查一个对象是否是特定类的实例或者该类的子类的实例。它通常用在条件语句中,以确定对象的类型,从而避免在向下转型时发生ClassCastException。在使用instanceof时,如果左边的实例属于右边的类或接口,或者是他们的子类,那么instanceof就会返回true,否则,返回false。这是一种类型安全的检查方式,用来保证在将对象转型为更具体的类型之前,这个对象确实是这个类型的,如下:if(objectinstanceofString){//返回true,确认是String类型,强制转换为String类型后使用Stringstr=
Java13于9月17日正式发布。JEP354:增强Switch表达式(第二次预览)Switch表达式是在Java12中首次作为预览特性引入,而在Java13中对Switch表达式做了增强改进:在块中引入了yield语句来返回值,而不是使用break。yield关键字用于从switch表达式的case块中返回一个值。这对于复杂的Switch语句特别有用,其中每个case块包含多行代码,并且最终需要返回一个值。更多阅读:Java13新特性—增强Switch表达式Java版本更新类型JEP更新内容Java12预览特性JEP325引入Switch表达式作为预览特性Java13第二次预览JEP354加
在Java13之前,我们有时候需要写多行字符串,比如拼接HTML、XML之类的,在处理这种字符串时我们往往需要通过使用\n实现换行,以及使用+符号连接多行字符串,例如:Stringhtml="<html>"+"<body>"+"<p>skjava.com</p>"+"</body>"+"</html>";这种方式不仅使代码难以阅读,也增加了维护的难度。而且如果字符串中包括了特殊字符,还需要转义,处理起来非常麻烦。所以为了解决
Java12引入Switch表达式作为预览特性,该特性与传统的Switch表达式相比,它允许将整个Switch结构作为一个表达式,直接返回值,而不是像老版本的Switch语句一样不支持返回值。同时它使用->箭头来代替传统的":",使得代码更加简洁、易读,也避免了使用冗长的break语句,杜绝了"Fall-through"行为。详情参考文章:Java12新特性—Switch表达式为了进一步扩展Switch的功能,Java13引入yield关键字来处理多分支结构中的返回值。yield用于在Switch表达式的每个分支中返回一个值,这点与传统的Switc
作为一个非长期支持(LTS)版本,Java12于2019年3月发布。JEP189:Shenandoah垃圾收集器(预览特性)Shenandoah垃圾收集器,一个专门用来处理大堆(Heap)和低延迟垃圾收集器,目前是一个实验性质的垃圾收集器。对于需要处理大量数据的应用,如高吞吐和大内存的应用,传统垃圾收集器在回收内存时可能导致明显的停顿。为了解决这个问题,尤其是在大内存需求的应用场景中,引入Shenandoah垃圾收集器。Shenandoah使用了一种用于并发压缩堆时维护对象引用的技术(BrooksPointers:布鲁克斯指针)。这种技术允许收集器在压缩堆时并行地移动对象,而不必暂停应用线程,
Java12引入Collectors.teeing(),进一步增强了Java的流(Stream)处理能力。teeing()允许对同时对一个流进行两种不同的收集操作,并将这两种操作的结果合并成一个。方法定义如下:Collectors.teeing(Collector<?superT,A,R1>downstream1,Collector<?superT,A,R2>downstream2,BiFunction<?superR1,?superR2,R>merger)downstream1和downstream2:两个不同的Collector实例。merger:一个B
为了能够以更简洁的方式显示大数字,Java12引入紧凑数字格式化(CompactNumberFormatting),这是对NumberFormat的一个补充。紧凑数字格式化,可以将十进制、货币或百分比的长数字格式化为短格式,例如将1,000格式化为1K,1,000,000为1M等。这种表达的方式特别适合需要在有限空间内显示数字的场景,如图表、用户界面。使用NumberFormat类的getCompactNumberInstance()就可以实现:@TestpublicvoidNumberFormatTest()throwsIOException{NumberFormatcompactForma