一、概述Java中的排序是由Comparable和Comparator这两个接口来提供的。Comparable表示可被排序的,实现该接口的类的对象自动拥有排序功能。Comparator则表示一个比较器,实现了该接口的的类的对象是一个针对目标类的对象定义的比较器,一般情况,这个比较器将作为一个参数进行传递。二、ComparableComparable的中文意思就是可被排序的,代表本身支持排序功能。只要我们的类实现了这个接口,那么这个类的对象就会自动拥有了可被排序的能力。而且这个排序被称为类的自然顺序。这个类的对象的列表可以被Collections.sort和Arrays.sort来执行排序。同时
概述equals方法和hashCode方法都是有Object类定义的。publicclassObject{publicnativeinthashCode();publicbooleanequals(Objectobj){return(this==obj);}}任何的类都是Object类的子类,所以它们默认都拥有这两个方法。equals方法用于定义两个对象的比较方式,而hashCode方法是native方法,主要用户计算对象的hash值。equalsequals方法主要用于定义两个对象的比较方式,默认的比较方式是比较内存地址,相对于基本类型来说就是值,而相对于引用类型来说就是堆中具体对象的地址。
概述Java源码中涉及到大量的二进制操作,非常的复杂,但非常的快速。Java二进制表示法首先了解下二进制,二进制是相对十进制而言的,当然还有八进制,十六进制等等,我们常用的都是十进制,计算机用的都是二进制,而符号表示常用十六进制。二进制就是只有0、1两个值表示的数,规则是逢二进一。整数表示法Java中使用补码来表示负数,具体就是除符号位之外,剩余位取反加1,符号位不变还是1(符号位0-正数,1-负数)Java中二进制符号位也不是固定的,在Byte类型的数值中,由于其为一个字节即八位取值范围为-128到127,其符号位就是第8位二进制位。如下所示:Byte型数据1->00000001-1-
一、概述final是Java关键字中最常见之一,表示“最终的,不可更改”之意,在Java中也正是这个意思。有final修饰的内容,就会变得与众不同,它们会变成终极存在,其内容成为固定的存在。finally关键字不同于final关键字,这是一个需要与异常体系结构配合使用的关键字,旨在定义必须要进行操作,一般用于在发生异常的时候进行一些收尾操作,比如释放资源等。另外还有个finalized,它是一个方法,它需要与垃圾收集体系配合使用。主要在对象被垃圾收集之前进行一些操作,这些操作只会被执行一次,即使一个对象多次被标记为下次进行垃圾收集,也只有第一次会执行。二、final作用2.1final修饰变量
一、概述static关键字是Java诸多关键字中较常使用的一个,从其本意可得其意:静态,何为静态呢?静,即不动,静止,固定不变之意(其实可以理解为存储位置不变)。Java中的静是相对于“动”而言的,所谓的动就是可变化的内容。当然这里指的是针对类而言的,静态内容指的是在类被JVM加载的时候就确定的内容,这部分内容只会被分配一次内存,即在内存中保留一份存储,动态内容则不同,它们是随类的对象创建而动的,每当创建一个对象的时候就会对这些内容分配一份内存,即每个对象都有自己独有的内存存储空间(其中保存着那些动态的内容)。静态的内容是属于类的,动态的内容属于对象。上面的描述是及其概括的描述,下面我们仔细的
一、序列化简介在项目中有很多情况需要对实例对象进行序列化与反序列化,这样可以持久的保存对象的状态,甚至在各个组件之间进行对象传递和远程调用。序列化机制是项目中必不可少的常用机制。要想一个类拥有序列化、反序列化功能,最简单的方法就是实现java.io.Serializable接口,这个接口是一个标记接口(markerInterface),即其内部无任何字段与方法定义。当我们定义了一个实现Serializable接口的类之后,一般我们会手动在类内部定义一个privatestaticfinallongserialVersionUID字段,用来保存当前类的序列版本号。这样做的目的就是唯一标识该类,其对
一、概述Java中的拷贝功能是由Object类的clone方法定义的。publicclassObject{//...protectednativeObjectclone()throwsCloneNotSupportedException;//...}这是一个可被重写的本地方法。这个方法是与Cloneable接口相关联的,如果针对一个没有实现Cloneable接口的方法执行器clone方法,会抛出CloneNotSupportedException异常。二、CloneableCloneable接口就是一个标记接口,表示实现了该接口的类具备了可以克隆的功能。一般来说,如果一个类实现了该接口,那么同
一、概述Optional的引入是为了解决null的问题,那么到底是解决null的什么问题呢?我们知道当我们针对null调用方法的之后,就会抛出空指针异常,Optional就是为了解决这个问题而来的。Optional通过封装目标对象的方式来表示,当我们使用的时候,Optional是必然存在的,因为如果结果为null,会返回一个固定的EMPTY实例,这样就不会存在null引用的问题了。那该如何来使用Optional呢?我们不能滥用Optional,只有在逻辑上(业务上)可能为null时才使用Optional来封装目标对象,如果逻辑上(业务上)肯定不可能为null时,就不要使用Optional封装对
一、概述Stream操作简称流操作,这里的流与IO流毫无关系,这里的流指的是流式操作,就是流水线操作。Stream流操作主要包包括三大模块:创建流操作、中间流操作、终结流操作。其中创建流主要是创建Stream对象。每个Stream对象只能使用一次终结操作。中间流操作指的是各种中间流操作方法,比如去重、过滤、排序等终结流操作指的结果操作,终结操作的目的是产生最终结果。二、创建流2.1基于数组创建流publicclassStreamTest{publicstaticvoidcreateStream(){//通过数组生成流int[]ints={1,2,3,4,5,6};IntStreams1=Arr
一、概述Collector是专门用来作为Stream的collect方法的参数的。publicinterfaceStream<T>extendsBaseStream<T,Stream<T>>{<R,A>Rcollect(Collector<?superT,A,R>collector);}而Collectors是作为生产具体Collector的工具类。二、CollectorCollector主要包含五个参数,它的行为也是由这五个参数来定义的,如下所示:publicinterfaceCollector<T,A,R>{//sup
一、概述JDK1.8引入了函数式编程,重点包括函数式接口、lambda表达式、方法引用等。所谓函数式编程就是将函数(一段操作)作为一个基本单位进行传递。以前的Java中参数只能是具体的变量,函数式编程打破这一规范,可以将整个方法作为一个参数传递。Java毕竟是面向对象的编程语言,你要传递的东西,必须是一个类或接口的对象或者一个基本类型变量,所以Java就定义了函数式接口,用来承载传递的函数。二、函数式接口2.1函数式接口函数式接口是在JDK1.8中提出的新概念,但对应的却是老结构,在以往版本的JDK中就已经存在这种结构,只是没有定义化。函数式接口就是只有一个抽象方法的接口。常用的函数式接口有R
1、动态代理(DynamicProxy)代理分为静态代理和动态代理,静态代理是在编译时就将接口、实现类、代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理,动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能。其实方法直接调用就可以完成功能,为什么还要加个代理呢?原因是采用代理模式可以有效的将具体的实现与调用方进行解耦,通过面向接口进行编码完全将具体的实现隐藏在内部。2、代理实现的一般模式其实代理的一般模式就是静态代理的实现模式:首先创建一个接口(JDK代理都是面向接口的),然后
instanceof关键字是在Java类中实现equals方法最常使用的关键字,表示其左边的对象是否是右边类型的实例,这里右边的类型可以扩展到继承、实现结构中,可以是其真实类型,或者真实类型的超类型、超接口类型等。instanceof左边必须是对象实例或者null类型,否则无法通过编译。instanceof右边必须是左边对象的可转换类型(可强转),否则无法通过编译。使用实例:interfaceIFather1{}interfaceISon1extendsIFather1{}classFather1implementsIFather1{}classSon1extendsFather1implem
Lombok注解解析:@NonNull使用在方法的参数或者构造器的参数上,用于生成null验证。Lombok可以识别任何第三方工具的字段上标注的@NonNull名称的注解,并在使用@Data、@AllArgsContruct进行生成方法和构造器时进行null判断。而Lombok的@NonNull注解使用在参数之上,仅仅作用到你自定义的方法和构造器之上。null判断会采用:if(param==null)thrownewNullPointerException("paramismarked@NonNullbutisnull");的形式插入,并且会在你方法的开头和构造器的this
一、概述Date类是从JDK1.1就开始存在的老类,其提供了针对日期进行操作的诸多方法,但其却一直饱受诟病,不同的起始编号,国际化的低支持,JDK官方也认识到这个问题,后台提出使用Calendar类进行日期操作,日期的格式化交给DateFormat,虽然我们已经不再使用Date类中的大多数方法,但是还有一部分保留的内容值的我们一谈。二、构造器Date类之前有6大构造器,其中四个已经标注弃用,我们不再看他,重点看另外两个:publicclassDateimplementsjava.io.Serializable,Cloneable,Comparable<Date>{/***Alloc
一、概述throw和throws就是异常相关的关键字,在java中异常机制是一个非常重要的机制,我们需要重点掌握。既然说到了异常,简单描述下异常机制很有必要,这也对后文的讲述提供前提。二、Java异常机制在Java中表示异常的接口是Exception,与其同一层次的还有一个Error接口,用于描述不可挽回的系统级错误,它们两个都继承自Throwable接口,这个接口是所有异常和错误的超接口。在Java中只有Throwable的实例才能在虚拟机或者java代码中被抛出,一切想要抛出的异常都必须作为Throwable的子类。异常又分为两种,一种是受检异常,另一种是未受检异常。受检异常是Java内部
一、概述Java官方推荐使用Calendar来替换Date的使用。Calendar与Date之间可以自由的进行转换,转换的纽带是time。使用Calendar的getTime()方法可以得到一个Date类型的对象,这个对象底层是使用Date的第二个带Long型参数的构造器创建的,这个Long型参数是Calendar中的time字段中保存的值,这个time字段的值是在具体的实现类中定义赋值的。比如GregorianCalendar中的实现computeTime(),这个方法的目的就是将field值转换为time值,这个涉及到Calendar中的两种模式,之后会有介绍。而通过Calendar的se
一、概述Java代码中的异常处理是非常重要的一环,从代码中可以看到,它的使用已经和业务逻辑紧密的结合在一起,部分业务逻辑还是依靠异常来完成的,更多的时候进行异常处理可以完善逻辑,避免可能的出错,规避小错误引发的大停顿。在一般的项目之中,都会自定义运行时异常,用以适应项目的需要,这种异常可被捕捉,也可不被捕捉,它们不会导致整个系统挂掉,但是很多情况下,不捕捉处理就会导致业务出错。在这里我们模拟几种情况,点明异常捕捉的使用时机。二、情况分析先来看没有任何处理的代码:publicclassExceptionTests01{publicstaticvoidmain(String[]args){Syst
一、this关键字this代表当前对象,它有以下几种用途:本类中在非静态方法中条用非静态变量和方法,就可以使用【this.变量名】和【this.方法名(参数列表)】的方式调用,实际情况是,this关键字通常会被省略。就在上面这种情况下,有一个特殊情况,那就是在方法中定义了一个与类成员变量同名的局部变量,这是在方法内部调用类的成员变量就必须使用this关键字来点用。在构造方法中使用:在存在构造方法重构(overlode)的类中,使用【this(参数列表)】的方式调用本类中的其他构造方法,且必须放置于构造方法的第一句。二、super关键字super代表父类对象,它与this不同,用途如下:子类重写
一、概述Java中单例有7种写法,这个是在面试中经常被问到的内容,而且有时候还要求手写单例实现方式。所以我们有必要认真的了解一下这七种写法。二、七种实现2.1懒汉式——线程不安全publicclassSingletonOne{publicstaticSingletonOnesingleton;privateSingletonOne(){}publicstaticSingletonOnegetSingleton(){if(singleton==null)returnnewSingletonOne();returnsingleton;}}懒汉式实现了懒加载,但是线程不安全,基本不会使用。2.2懒汉
一、SPI是什么SPI是相对API而言的。API指的是应用对服务调用方提供的接口,用于提供某种服务、功能,面向的是服务调用方。SPI指的是应用对服务实现方提供的接口,用于实现某种服务、功能,面向的是服务实现方二、SPI的使用2.1第一步:创建服务接口packagecom.dh.spi;publicinterfaceFruit{StringgetName();}2.2第二步:创建多个服务实现packagecom.dh.spi;publicclassAppleimplementsFruit{@OverridepublicStringgetName(){return"apple"
一、概述Java提供了有关时间的类和API,可以很方便的处理日期时间。JDK1.8之前使用的是Date和Calendar,JDK1.8之后使用DateTime,前者毛病较多,后者更加适用。二、基础知识2.1时区我们都知道,地球是圆的,并且在不停的自转与公转,自转一圈是为一天,公转一圈是为一年。我们这里关注自转的部分。圆形的地球总是存在面向太阳的半球与背向太阳的半球,面向太阳的半球为白天,背向太阳的半球为黑夜,边界区域为凌晨和傍晚。那么在这些处于地球不同位置的地区的时间也怎么分配的呢?如果我们规定一个统一的时间,让全球共用。这样的话,0点时分,全球将拥有各种不同的景象,有的在凌晨,有的在早晨,有
JDK6和JDK7中substring的原理及区别substring(intbeginIndex,intendIndex)方法用于截取字符串,返回截取的新字符串。新字符串由当前字符串的第beginIndex到endIndex的字符组成,长度无endIndex-beginIndex。JDK6中的实现原理publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence{//JDK6String(intoffset,intcount,charvalue[]){this.value=va
一、概述枚举就是一个语法糖效果。定义一个枚举,其实就是定义一个继承抽象类Enum的类。了解了Enum,就能了解枚举。二、Enum解析2.1接口publicabstractclassEnum<EextendsEnum<E>>implementsComparable<E>,Serializable{}枚举类实现了Comparable和Serializable接口,那么也就意味着,每个枚举类都拥有比较(有序)和序列化功能。2.2属性publicabstractclassEnum<EextendsEnum<E>>implementsCompa