csdn_export_md

使用RabbitMQ有什么好处?

  • 解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
  • 异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
  • 削峰,并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常

使用RabbitMQ有什么缺点?

  • 系统可用性降低

本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;

  • 系统复杂度提高

加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。

  • 一致性问题

A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

ActiveMQRabbitMQRocketMQKafkaZeroMQ
单机吞吐量比RabbitMQ低2.6w/s(消息做持久化)11.6w/s17.3w/s29w/s
开发语言JavaErlangJavaScala/JavaC
主要维护者ApacheMozilla/SpringAlibabaApacheiMatix,创始人已去世
成熟度成熟成熟开源版本不够成熟比较成熟只有C、PHP等版本成熟
订阅形式点对点(p2p)、广播(发布-订阅)提供了4种:direct, topic ,Headers和fanout。fanout就是广播模式基于topic/messageTag以及按照消息类型、属性进行正则匹配的发布订阅模式基于topic以及按照topic进行正则匹配的发布订阅模式点对点(p2p)
持久化支持少量堆积支持少量堆积支持大量堆积支持大量堆积不支持
顺序消息不支持不支持支持支持不支持
性能稳定性一般较差很好
集群方式支持简单集群模式,比如’主-备’,对高级集群模式支持不好。支持简单集群,'复制’模式,对高级集群模式支持不好。常用 多对’Master-Slave’ 模式,开源版本需手动切换Slave变成Master天然的‘Leader-Slave’无状态集群,每台服务器既是Master也是Slave不支持
管理界面一般较好一般

MQ 的常见问题有:

  1. 消息的顺序问题

    消息有序指的是可以按照消息的发送顺序来消费。

  2. 消息的重复问题

    造成消息重复的根本原因是:网络不可达。

    所以解决这个问题的办法就是绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?

    消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现。利用一张日志表来记录已经处理成功的消息的 ID,如果新到的消息 ID 已经在日志表中,那么就不再处理这条消息。

什么是RabbitMQ?

​ RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的消息中间件

rabbitmq 的使用场景

(1)服务间异步通信

(2)顺序消费

(3)定时任务

(4)请求削峰

消息基于什么传输

由于TCP连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制。

消息怎么路由?

从概念上来说,消息路由必须有三部分:交换器、路由、绑定。生产者把消息发布到交换器上;绑定决定了消息如何从路由器路由到特定的队列;消息最终到达队列,并被消费者接收。

消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。
通过队列路由键,可以把队列绑定到交换器上。
消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中;如果不能匹配到任何队列,消息将进入 “黑洞”。

常用的交换器主要分为一下三种:

  • direct:如果路由键完全匹配,消息就被投递到相应的队列
  • fanout:如果交换器收到消息,将会广播到所有绑定的队列上
  • topic:可以使来自不同源头的消息能够到达同一个队列。 使用topic交换器时,可以使用通配符,比如:“*” 匹配特定位置的任意文本, “.” 把路由键分为了几部分,“#” 匹配所有规则等。特别注意:发往topic交换器的消息不能随意的设置选择键(routing_key),必须是由"."隔开的一系列的标识符组成。

如何确保消息正确地发送至RabbitMQ?

RabbitMQ使用发送方确认模式,确保消息正确地发送到RabbitMQ。发送方确认模式:将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(not acknowledged,未确认)消息。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

如何确保消息接收方消费了消息?

接收方消息确认机制:消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。

下面罗列几种特殊情况:

如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要根据bizId去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给该消费者分发更多的消息。

如何避免消息重复投递或重复消费?

在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列;在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。

这个问题针对业务场景来答分以下几点:

1.比如,你拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

2.再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。

3.如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

如何解决丢数据的问题?

1.生产者丢数据

生产者的消息没有投递到MQ中怎么办?从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息。

transaction机制就是说,发送消息前,开启事物(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事物就会回滚(channel.txRollback()),如果发送成功则提交事物(channel.txCommit())。

然而缺点就是吞吐量下降了。因此,按照博主的经验,生产上用confirm模式的居多。一旦channel进入confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.如果rabiitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

2.消息队列丢数据

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

①、将queue的持久化标识durable设置为true,则代表是一个持久的队列

②、发送消息的时候将deliveryMode=2

这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据。在消息还没有持久化到硬盘时,可能服务已经死掉,这种情况可以通过引入mirrored-queue即镜像队列,但也不能保证消息百分百不丢失(整个集群都挂掉)

3.消费者丢数据

启用手动确认模式可以解决这个问题

①自动确认模式,消费者挂掉,待ack的消息回归到队列中。消费者抛出异常,消息会不断的被重发,直到处理成功。不会丢失消息,即便服务挂掉,没有处理完成的消息会重回队列,但是异常会让消息不断重试。

②手动确认模式,如果消费者来不及处理就死掉时,没有响应ack时会重复发送一条信息给其他消费者;如果监听程序处理异常了,且未对异常进行捕获,会一直重复接收消息,然后一直抛异常;如果对异常进行了捕获,但是没有在finally里ack,也会一直重复发送消息(重试机制)。

③不确认模式,acknowledge=“none” 不使用确认机制,只要消息发送完成会立即在队列移除,无论客户端异常还是断开,只要发送完就移除,不会重发。

14、死信队列和延迟队列的使用

死信消息:

  • 1 消息被拒绝(Basic.Reject或Basic.Nack)并且设置 requeue 参数的值为 false

  • 2消息过期了-

  • 3队列达到最大的长度
    过期消息:

    在 rabbitmq 中存在2种方可设置消息的过期时间,第一种通过对队列进行设置,这种设置后,该队列中所有的消息都存在相同的过期时间,第二种通过对消息本身进行设置,那么每条消息的过期时间都不一样。如果同时使用这2种方法,那么以过期时间小的那个数值为准。当消息达到过期时间还没有被消费,那么那个消息就成为了一个 死信 消息。

    队列设置:在队列申明的时候使用 x-message-ttl 参数,单位为 毫秒

    单个消息设置:是设置消息属性的 expiration 参数的值,单位为 毫秒

延时队列:在rabbitmq中不存在延时队列,但是我们可以通过设置消息的过期时间和死信队列来模拟出延时队列。消费者监听死信交换器绑定的队列,而不要监听消息发送的队列。

有了以上的基础知识,我们完成以下需求:

需求:用户在系统中创建一个订单,如果超过时间用户没有进行支付,那么自动取消订单。

分析:

    1、上面这个情况,我们就适合使用延时队列来实现,那么延时队列如何创建

    2、延时队列可以由 过期消息+死信队列 来时间

    3、过期消息通过队列中设置 x-message-ttl 参数实现

    4、死信队列通过在队列申明时,给队列设置 x-dead-letter-exchange 参数,然后另外申明一个队列绑定x-dead-letter-exchange对应的交换器。
```" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                                            <p></p><div class="toc"><h3><a name="t0"></a><a name="t0"></a>文章目录</h3><ul><ul><li><a href="#Java_35" rel="nofollow" target="_self">Java概述</a></li><ul><li><a href="#_37" rel="nofollow" target="_self">何为编程</a></li><li><a href="#Java_45" rel="nofollow" target="_self">什么是Java</a></li><li><a href="#jdk15_51" rel="nofollow" target="_self">jdk1.5之后的三大版本</a></li><li><a href="#JVMJREJDK_62" rel="nofollow" target="_self">JVM、JRE和JDK的关系</a></li><li><a href="#_82" rel="nofollow" target="_self">什么是跨平台性?原理是什么</a></li><li><a href="#Java_90" rel="nofollow" target="_self">Java语言有哪些特点</a></li><li><a href="#_108" rel="nofollow" target="_self">什么是字节码?采用字节码的最大好处是什么</a></li><li><a href="#Java_126" rel="nofollow" target="_self">什么是Java程序的主类?应用程序和小程序的主类有何不同?</a></li><li><a href="#Java_132" rel="nofollow" target="_self">Java应用程序与小程序之间有那些差别?</a></li><li><a href="#JavaC_138" rel="nofollow" target="_self">Java和C++的区别</a></li><li><a href="#Oracle_JDK__OpenJDK__149" rel="nofollow" target="_self">Oracle JDK 和 OpenJDK 的对比</a></li></ul><li><a href="#_165" rel="nofollow" target="_self">基础语法</a></li><ul><li><a href="#_167" rel="nofollow" target="_self">数据类型</a></li><ul><li><a href="#Java_169" rel="nofollow" target="_self">Java有哪些数据类型</a></li><li><a href="#switch__byte__long__String__192" rel="nofollow" target="_self">switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上</a></li><li><a href="#_2__8_198" rel="nofollow" target="_self">用最有效率的方法计算 2 乘以 8</a></li><li><a href="#Mathround115_Mathround115_204" rel="nofollow" target="_self">Math.round(11.5) 等于多少?Math.round(-11.5)等于多少</a></li><li><a href="#float_f34_210" rel="nofollow" target="_self">float f=3.4;是否正确</a></li><li><a href="#short_s1__1_s1__s1__1short_s1__1_s1__1_216" rel="nofollow" target="_self">short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗</a></li></ul><li><a href="#_224" rel="nofollow" target="_self">编码</a></li><ul><li><a href="#Java_226" rel="nofollow" target="_self">Java语言采用何种编码方案?有何特点?</a></li></ul><li><a href="#_232" rel="nofollow" target="_self">注释</a></li><ul><li><a href="#Java_234" rel="nofollow" target="_self">什么Java注释</a></li></ul><li><a href="#_257" rel="nofollow" target="_self">访问修饰符</a></li><ul><li><a href="#_publicprivateprotected_259" rel="nofollow" target="_self">访问修饰符 public,private,protected,以及不写(默认)时的区别</a></li></ul><li><a href="#_276" rel="nofollow" target="_self">运算符</a></li><ul><li><a href="#_278" rel="nofollow" target="_self">&amp;和&amp;&amp;的区别</a></li></ul><li><a href="#_288" rel="nofollow" target="_self">关键字</a></li><ul><li><a href="#Java__goto_290" rel="nofollow" target="_self">Java 有没有 goto</a></li><li><a href="#final__296" rel="nofollow" target="_self">final 有什么用?</a></li><li><a href="#final_finally_finalize_306" rel="nofollow" target="_self">final finally finalize区别</a></li><li><a href="#this_318" rel="nofollow" target="_self">this关键字的用法</a></li><li><a href="#super_357" rel="nofollow" target="_self">super关键字的用法</a></li><li><a href="#thissuper_412" rel="nofollow" target="_self">this与super的区别</a></li><li><a href="#static_425" rel="nofollow" target="_self">static存在的主要意义</a></li><li><a href="#static_435" rel="nofollow" target="_self">static的独特之处</a></li><li><a href="#static_449" rel="nofollow" target="_self">static应用场景</a></li><li><a href="#static_459" rel="nofollow" target="_self">static注意事项</a></li></ul><li><a href="#_465" rel="nofollow" target="_self">流程控制语句</a></li><ul><li><a href="#break_continue_return__467" rel="nofollow" target="_self">break ,continue ,return 的区别及作用</a></li><li><a href="#_Java__477" rel="nofollow" target="_self">在 Java 中,如何跳出当前的多重嵌套循环</a></li></ul></ul><li><a href="#_500" rel="nofollow" target="_self">面向对象</a></li><ul><li><a href="#_502" rel="nofollow" target="_self">面向对象概述</a></li><ul><li><a href="#_504" rel="nofollow" target="_self">面向对象和面向过程的区别</a></li></ul><li><a href="#_528" rel="nofollow" target="_self">面向对象三大特性</a></li><ul><li><a href="#_530" rel="nofollow" target="_self">面向对象的特征有哪些方面</a></li><li><a href="#Java_593" rel="nofollow" target="_self">什么是多态机制?Java语言是如何实现多态的?</a></li><li><a href="#_619" rel="nofollow" target="_self">面向对象五大基本原则是什么(可选)</a></li></ul><li><a href="#_634" rel="nofollow" target="_self">类与接口</a></li><ul><li><a href="#_636" rel="nofollow" target="_self">抽象类和接口的对比</a></li><li><a href="#_672" rel="nofollow" target="_self">普通类和抽象类有哪些区别?</a></li><li><a href="#_final__679" rel="nofollow" target="_self">抽象类能使用 final 修饰吗?</a></li><li><a href="#_685" rel="nofollow" target="_self">创建一个对象用什么关键字?对象实例与对象引用有何不同?</a></li></ul><li><a href="#_691" rel="nofollow" target="_self">变量与方法</a></li><ul><li><a href="#_693" rel="nofollow" target="_self">成员变量与局部变量的区别有哪些</a></li><li><a href="#Java_733" rel="nofollow" target="_self">在Java中定义一个不做事且没有参数的构造方法的作用</a></li><li><a href="#_739" rel="nofollow" target="_self">在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?</a></li><li><a href="#_745" rel="nofollow" target="_self">一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?</a></li><li><a href="#_751" rel="nofollow" target="_self">构造方法有哪些特性?</a></li><li><a href="#_761" rel="nofollow" target="_self">静态变量和实例变量区别</a></li><li><a href="#_769" rel="nofollow" target="_self">静态变量与普通变量区别</a></li><li><a href="#_777" rel="nofollow" target="_self">静态方法和实例方法有何不同?</a></li><li><a href="#_786" rel="nofollow" target="_self">在一个静态方法内调用一个非静态成员为什么是非法的?</a></li><li><a href="#_792" rel="nofollow" target="_self">什么是方法的返回值?返回值的作用是什么?</a></li></ul><li><a href="#_798" rel="nofollow" target="_self">内部类</a></li><ul><li><a href="#_800" rel="nofollow" target="_self">什么是内部类?</a></li><li><a href="#_806" rel="nofollow" target="_self">内部类的分类有哪些</a></li><ul><li><a href="#_810" rel="nofollow" target="_self">静态内部类</a></li><li><a href="#_834" rel="nofollow" target="_self">成员内部类</a></li><li><a href="#_861" rel="nofollow" target="_self">局部内部类</a></li><li><a href="#_908" rel="nofollow" target="_self">匿名内部类</a></li></ul><li><a href="#_948" rel="nofollow" target="_self">内部类的优点</a></li><li><a href="#_959" rel="nofollow" target="_self">内部类有哪些应用场景</a></li><li><a href="#final_968" rel="nofollow" target="_self">局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?</a></li><li><a href="#_993" rel="nofollow" target="_self">内部类相关,看程序说出运行结果</a></li></ul><li><a href="#_1027" rel="nofollow" target="_self">重写与重载</a></li><ul><li><a href="#constructoroverride_1029" rel="nofollow" target="_self">构造器(constructor)是否可被重写(override)</a></li><li><a href="#OverloadOverride_1035" rel="nofollow" target="_self">重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?</a></li></ul><li><a href="#_1045" rel="nofollow" target="_self">对象相等判断</a></li><ul><li><a href="#__equals__1047" rel="nofollow" target="_self">== 和 equals 的区别是什么</a></li><li><a href="#hashCode__equals__1086" rel="nofollow" target="_self">hashCode 与 equals (重要)</a></li><li><a href="#_1126" rel="nofollow" target="_self">对象的相等与指向他们的引用相等,两者有什么不同?</a></li></ul><li><a href="#_1132" rel="nofollow" target="_self">值传递</a></li><ul><li><a href="#_1134" rel="nofollow" target="_self">当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递</a></li><li><a href="#_Java__1140" rel="nofollow" target="_self">为什么 Java 中只有值传递</a></li><li><a href="#_1286" rel="nofollow" target="_self">值传递和引用传递有什么区别</a></li></ul><li><a href="#Java_1294" rel="nofollow" target="_self">Java包</a></li><ul><li><a href="#JDK__1296" rel="nofollow" target="_self">JDK 中常用的包有哪些</a></li><li><a href="#import_javajavax_1307" rel="nofollow" target="_self">import java和javax有什么区别</a></li></ul></ul><li><a href="#IO_1317" rel="nofollow" target="_self">IO流</a></li><ul><li><a href="#java__IO__1319" rel="nofollow" target="_self">java 中 IO 流分为几种?</a></li><li><a href="#BIONIOAIO__1341" rel="nofollow" target="_self">BIO,NIO,AIO 有什么区别?</a></li><li><a href="#Files_1357" rel="nofollow" target="_self">Files的常用方法都有哪些?</a></li></ul><li><a href="#_1371" rel="nofollow" target="_self">反射</a></li><ul><li><a href="#_1373" rel="nofollow" target="_self">什么是反射机制?</a></li><li><a href="#_1384" rel="nofollow" target="_self">反射机制优缺点</a></li><li><a href="#_1391" rel="nofollow" target="_self">反射机制的应用场景有哪些?</a></li><li><a href="#Java_1401" rel="nofollow" target="_self">Java获取反射的三种方法</a></li></ul><li><a href="#_1436" rel="nofollow" target="_self">网络编程</a></li><li><a href="#API_1442" rel="nofollow" target="_self">常用API</a></li><ul><li><a href="#String_1444" rel="nofollow" target="_self">String相关</a></li><ul><li><a href="#_1446" rel="nofollow" target="_self">字符型常量和字符串常量的区别</a></li><li><a href="#_1454" rel="nofollow" target="_self">什么是字符串常量池?</a></li><li><a href="#String__1460" rel="nofollow" target="_self">String 是最基本的数据类型吗</a></li><li><a href="#String_1470" rel="nofollow" target="_self">String有哪些特性</a></li><li><a href="#String_1480" rel="nofollow" target="_self">String为什么是不可变的吗?</a></li><li><a href="#String_1491" rel="nofollow" target="_self">String真的是不可变的吗?</a></li><li><a href="#_String__1549" rel="nofollow" target="_self">是否可以继承 String 类</a></li><li><a href="#String_stri_String_strnew_Stringi_1555" rel="nofollow" target="_self">String str="i"与 String str=new String("i")一样吗?</a></li><li><a href="#String_s__new_Stringxyz_1561" rel="nofollow" target="_self">String s = new String("xyz");创建了几个字符串对象</a></li><li><a href="#_1582" rel="nofollow" target="_self">如何将字符串反转?</a></li><li><a href="#_lengthString__length_1601" rel="nofollow" target="_self">数组有没有 length()方法?String 有没有 length()方法</a></li><li><a href="#String__1607" rel="nofollow" target="_self">String 类的常用方法都有那些?</a></li><li><a href="#_HashMap__String__key__1623" rel="nofollow" target="_self">在使用 HashMap 的时候,用 String 做 key 有什么好处?</a></li><li><a href="#StringStringBufferStringBuilderString_1629" rel="nofollow" target="_self">String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的</a></li></ul><li><a href="#Date_1655" rel="nofollow" target="_self">Date相关</a></li><li><a href="#_1659" rel="nofollow" target="_self">包装类相关</a></li><ul><li><a href="#_1661" rel="nofollow" target="_self">自动装箱与拆箱</a></li><li><a href="#int__Integer__1669" rel="nofollow" target="_self">int 和 Integer 有什么区别</a></li><li><a href="#Integer_a_127__Integer_b__127_1681" rel="nofollow" target="_self">Integer a= 127 与 Integer b = 127相等吗</a></li></ul></ul><li><a href="#_1709" rel="nofollow" target="_self">常用工具类库</a></li><li><a href="#_1713" rel="nofollow" target="_self">单元测试</a></li><li><a href="#_1717" rel="nofollow" target="_self">日志</a></li></ul></ul></div><p></p>
<p>Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,MyBatis,数据库,中间件等,包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大部分知识。欢迎大家阅读,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,在此表示感激不尽。文章持续更新中…</p>

<div class="table-box"><table>
<thead>
<tr>
<th>序号</th>
<th>内容</th>
<th>链接地址</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Java基础知识面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104390612" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104390612</a></td>
</tr>
<tr>
<td>2</td>
<td>Java集合容器面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104588551" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104588551</a></td>
</tr>
<tr>
<td>3</td>
<td>Java异常面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104390689" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104390689</a></td>
</tr>
<tr>
<td>4</td>
<td>并发编程面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104863992" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104863992</a></td>
</tr>
<tr>
<td>5</td>
<td>JVM面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104390752" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104390752</a></td>
</tr>
<tr>
<td>6</td>
<td>Spring面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397516" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397516</a></td>
</tr>
<tr>
<td>7</td>
<td>Spring MVC面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397427" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397427</a></td>
</tr>
<tr>
<td>8</td>
<td>Spring Boot面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397299" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397299</a></td>
</tr>
<tr>
<td>9</td>
<td>Spring Cloud面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397367" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397367</a></td>
</tr>
<tr>
<td>10</td>
<td>MyBatis面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/101292950" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/101292950</a></td>
</tr>
<tr>
<td>11</td>
<td>Redis面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/103522351" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/103522351</a></td>
</tr>
<tr>
<td>12</td>
<td>MySQL数据库面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104778621" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104778621</a></td>
</tr>
<tr>
<td>13</td>
<td>消息中间件MQ与RabbitMQ面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104588612" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104588612</a></td>
</tr>
<tr>
<td>14</td>
<td>Dubbo面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104390006" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104390006</a></td>
</tr>
<tr>
<td>15</td>
<td>Linux面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104588679" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104588679</a></td>
</tr>
<tr>
<td>16</td>
<td>Tomcat面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397665" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397665</a></td>
</tr>
<tr>
<td>17</td>
<td>ZooKeeper面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104397719" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104397719</a></td>
</tr>
<tr>
<td>18</td>
<td>Netty面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/104391081" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/104391081</a></td>
</tr>
<tr>
<td>19</td>
<td>架构设计&amp;分布式&amp;数据结构与算法面试题(2020最新版)</td>
<td><a href="https://thinkwon.blog.csdn.net/article/details/105870730" rel="nofollow">https://thinkwon.blog.csdn.net/article/details/105870730</a></td>
</tr>
</tbody>
</table></div><h2><a name="t1"></a><a name="t1"></a><a id="Java_35"></a>Java概述</h2>
<h3><a name="t2"></a><a name="t2"></a><a id="_37"></a>何为编程</h3>
<p>编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。</p>
<p>为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。</p>
<h3><a name="t3"></a><a name="t3"></a><a id="Java_45"></a>什么是Java</h3>
<p>Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。</p>
<h3><a name="t4"></a><a name="t4"></a><a id="jdk15_51"></a>jdk1.5之后的三大版本</h3>
<ul>
<li>Java SE(J2SE,Java 2 Platform Standard Edition,标准版)<br>
Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为Java EE和Java ME提供基础。</li>
<li>Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)<br>
Java EE 以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0应用程序。2018年2月,Eclipse 宣布正式将 JavaEE 更名为 JakartaEE</li>
<li>Java ME(J2ME,Java 2 Platform Micro Edition,微型版)<br>
Java ME 以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。</li>
</ul>
<h3><a name="t5"></a><a name="t5"></a><a id="JVMJREJDK_62"></a>JVM、JRE和JDK的关系</h3>
<p>JVM<br>
Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。</p>
<p>JRE<br>
Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包</p>
<p>如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。</p>
<p>JDK<br>
Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等</p>
<p>JVM&amp;JRE&amp;JDK关系图</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0pvdXJXb24vaW1hZ2UvbWFzdGVyL0phdmElRTclQUUlODAlRTQlQkIlOEIvSlZNJkpSRSZKREslRTUlODUlQjMlRTclQjMlQkIlRTUlOUIlQkUucG5n?x-oss-process=image/format,png" alt=""></p>
<h3><a name="t6"></a><a name="t6"></a><a id="_82"></a>什么是跨平台性?原理是什么</h3>
<p>所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。</p>
<p>实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。</p>
<h3><a name="t7"></a><a name="t7"></a><a id="Java_90"></a>Java语言有哪些特点</h3>
<p>简单易学(Java语言的语法与C语言和C++语言很接近)</p>
<p>面向对象(封装,继承,多态)</p>
<p>平台无关性(Java虚拟机实现平台无关性)</p>
<p>支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)</p>
<p>支持多线程(多线程机制使应用程序在同一时间并行执行多项任)</p>
<p>健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)</p>
<p>安全性</p>
<h3><a name="t8"></a><a name="t8"></a><a id="_108"></a>什么是字节码?采用字节码的最大好处是什么</h3>
<p><strong>字节码</strong>:Java源代码经过虚拟机编译器编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。</p>
<p><strong>采用字节码的好处</strong>:</p>
<p>Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。</p>
<p><strong>先看下java中的编译器和解释器</strong>:</p>
<p>Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">Java源代码<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">&gt;</span>编译器<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">&gt;</span>jvm可执行的Java字节码<span class="token punctuation">(</span>即虚拟指令<span class="token punctuation">)</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">&gt;</span>jvm<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">&gt;</span>jvm中解释器<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span><span class="token operator">&gt;</span>机器可执行的二进制机器码<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">&gt;</span>程序运行。
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li></ul></pre>
<h3><a name="t9"></a><a name="t9"></a><a id="Java_126"></a>什么是Java程序的主类?应用程序和小程序的主类有何不同?</h3>
<p>一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。</p>
<h3><a name="t10"></a><a name="t10"></a><a id="Java_132"></a>Java应用程序与小程序之间有那些差别?</h3>
<p>简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。</p>
<h3><a name="t11"></a><a name="t11"></a><a id="JavaC_138"></a>Java和C++的区别</h3>
<p>我知道很多人没学过C++,但是面试官就是没事喜欢拿咱们Java和C++比呀!没办法!!!就算没学过C++,也要记下来!</p>
<ul>
<li>都是面向对象的语言,都支持封装、继承和多态</li>
<li>Java不提供指针来直接访问内存,程序内存更加安全</li>
<li>Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。</li>
<li>Java有自动内存管理机制,不需要程序员手动释放无用内存</li>
</ul>
<h3><a name="t12"></a><a name="t12"></a><a id="Oracle_JDK__OpenJDK__149"></a>Oracle JDK 和 OpenJDK 的对比</h3>
<ol>
<li>
<p>Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;</p>
</li>
<li>
<p>OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;</p>
</li>
<li>
<p>Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;</p>
</li>
<li>
<p>在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;</p>
</li>
<li>
<p>Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;</p>
</li>
<li>
<p>Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。</p>
</li>
</ol>
<h2><a name="t13"></a><a name="t13"></a><a id="_165"></a>基础语法</h2>
<h3><a name="t14"></a><a name="t14"></a><a id="_167"></a>数据类型</h3>
<h4><a id="Java_169"></a>Java有哪些数据类型</h4>
<p><strong>定义</strong>:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。</p>
<p><strong>分类</strong></p>
<ul>
<li>基本数据类型
<ul>
<li>数值型
<ul>
<li>整数类型(byte,short,int,long)</li>
<li>浮点类型(float,double)</li>
</ul>
</li>
<li>字符型(char)</li>
<li>布尔型(boolean)</li>
</ul>
</li>
<li>引用数据类型
<ul>
<li>类(class)</li>
<li>接口(interface)</li>
<li>数组([])</li>
</ul>
</li>
</ul>
<p><strong>Java基本数据类型图</strong></p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0pvdXJXb24vaW1hZ2UvbWFzdGVyL0phdmElRTUlOUYlQkElRTclQTElODAlRTglQUYlQUQlRTYlQjMlOTUvSmF2YSVFNSU5RiVCQSVFNiU5QyVBQyVFNiU5NSVCMCVFNiU4RCVBRSVFNyVCMSVCQiVFNSU5RSU4Qi5wbmc?x-oss-process=image/format,png" alt=""></p>
<h4><a id="switch__byte__long__String__192"></a>switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上</h4>
<p>在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。</p>
<h4><a id="_2__8_198"></a>用最有效率的方法计算 2 乘以 8</h4>
<p>2 &lt;&lt; 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。</p>
<h4><a id="Mathround115_Mathround115_204"></a>Math.round(11.5) 等于多少?Math.round(-11.5)等于多少</h4>
<p>Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加 0.5 然后进行下取整。</p>
<h4><a id="float_f34_210"></a>float f=3.4;是否正确</h4>
<p>不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。</p>
<h4><a id="short_s1__1_s1__s1__1short_s1__1_s1__1_216"></a>short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗</h4>
<p>对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。</p>
<p>而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。</p>
<h3><a name="t15"></a><a name="t15"></a><a id="_224"></a>编码</h3>
<h4><a id="Java_226"></a>Java语言采用何种编码方案?有何特点?</h4>
<p>Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。</p>
<h3><a name="t16"></a><a name="t16"></a><a id="_232"></a>注释</h3>
<h4><a id="Java_234"></a>什么Java注释</h4>
<p><strong>定义</strong>:用于解释说明程序的文字</p>
<p><strong>分类</strong></p>
<ul>
<li>单行注释<br>
格式: // 注释文字</li>
<li>多行注释<br>
格式: /*  注释文字  */</li>
<li>文档注释<br>
格式:/** 注释文字 */</li>
</ul>
<p><strong>作用</strong></p>
<p>在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,注释的部分不会对程序的执行结果产生任何影响。</p>
<p>注意事项:多行和文档注释都不能嵌套使用。</p>
<h3><a name="t17"></a><a name="t17"></a><a id="_257"></a>访问修饰符</h3>
<h4><a id="_publicprivateprotected_259"></a>访问修饰符 public,private,protected,以及不写(默认)时的区别</h4>
<p><strong>定义</strong>:Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。</p>
<p><strong>分类</strong></p>
<p>private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)<br>
default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。<br>
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。<br>
public : 对所有类可见。使用对象:类、接口、变量、方法</p>
<p><strong>访问修饰符图</strong></p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0pvdXJXb24vaW1hZ2UvbWFzdGVyL0phdmElRTUlOUYlQkElRTclQTElODAlRTglQUYlQUQlRTYlQjMlOTUvSmF2YSVFOCVBRSVCRiVFOSU5NyVBRSVFNCVCRiVBRSVFOSVBNSVCMCVFNyVBQyVBNi5wbmc?x-oss-process=image/format,png" alt=""></p>
<h3><a name="t18"></a><a name="t18"></a><a id="_276"></a>运算符</h3>
<h4><a id="_278"></a>&amp;和&amp;&amp;的区别</h4>
<p>&amp;运算符有两种用法:(1)按位与;(2)逻辑与。</p>
<p>&amp;&amp;运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&amp;&amp;之所以称为短路运算,是因为如果&amp;&amp;左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。</p>
<p>注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。</p>
<h3><a name="t19"></a><a name="t19"></a><a id="_288"></a>关键字</h3>
<h4><a id="Java__goto_290"></a>Java 有没有 goto</h4>
<p>goto 是 Java 中的保留字,在目前版本的 Java 中没有使用。</p>
<h4><a id="final__296"></a>final 有什么用?</h4>
<p>用于修饰类、属性和方法;</p>
<ul>
<li>被final修饰的类不可以被继承</li>
<li>被final修饰的方法不可以被重写</li>
<li>被final修饰的变量不可以被改变,被final修饰不可变的是变量的引用,而不是引用指向的内容,引用指向的内容是可以改变的</li>
</ul>
<h4><a id="final_finally_finalize_306"></a>final finally finalize区别</h4>
<ul>
<li>final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表<br>
示该变量是一个常量不能被重新赋值。</li>
<li>finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块<br>
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。</li>
<li>finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调<br>
用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的<br>
最后判断。</li>
</ul>
<h4><a id="this_318"></a>this关键字的用法</h4>
<p>this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。</p>
<p>this的用法在java中大体可以分为3种:</p>
<p>1.普通的直接引用,this相当于是指向当前对象本身。</p>
<p>2.形参与成员名字重名,用this来区分:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token function">Person</span><span class="token punctuation">(</span>String name<span class="token punctuation">,</span> <span class="token keyword">int</span> age<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li></ul></pre>
<p>3.引用本类的构造函数</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">class</span> <span class="token class-name">Person</span><span class="token punctuation">{</span>
    <span class="token keyword">private</span> String name<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> age<span class="token punctuation">;</span>
    
    <span class="token keyword">public</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">public</span> <span class="token function">Person</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token function">Person</span><span class="token punctuation">(</span>String name<span class="token punctuation">,</span> <span class="token keyword">int</span> age<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li></ul></pre>
<h4><a id="super_357"></a>super关键字的用法</h4>
<p>super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。</p>
<p>super也有三种用法:</p>
<p>1.普通的直接引用</p>
<p>与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。</p>
<p>2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">class</span> <span class="token class-name">Person</span><span class="token punctuation">{</span>
    <span class="token keyword">protected</span> String name<span class="token punctuation">;</span>
 
    <span class="token keyword">public</span> <span class="token function">Person</span><span class="token punctuation">(</span>String name<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
 
<span class="token punctuation">}</span>
 
<span class="token keyword">class</span> <span class="token class-name">Student</span> <span class="token keyword">extends</span> <span class="token class-name">Person</span><span class="token punctuation">{</span>
    <span class="token keyword">private</span> String name<span class="token punctuation">;</span>
 
    <span class="token keyword">public</span> <span class="token function">Student</span><span class="token punctuation">(</span>String name<span class="token punctuation">,</span> String name1<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">super</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name1<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>      <span class="token comment">//Child</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token keyword">super</span><span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token comment">//Father</span>
    <span class="token punctuation">}</span>
 
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
       Student s1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Student</span><span class="token punctuation">(</span><span class="token string">"Father"</span><span class="token punctuation">,</span><span class="token string">"Child"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       s1<span class="token punctuation">.</span><span class="token function">getInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">19</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">20</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">21</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">22</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">23</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">24</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">25</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">26</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">27</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">28</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">29</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">30</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">31</li></ul></pre>
<p>3.引用父类构造函数</p>
<p>3、引用父类构造函数</p>
<ul>
<li>super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。</li>
<li>this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。</li>
</ul>
<h4><a id="thissuper_412"></a>this与super的区别</h4>
<ul>
<li>super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名  super.成员函数据名(实参)</li>
<li>this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)</li>
<li>super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。</li>
<li>super()和this()均需放在构造方法内第一行。</li>
<li>尽管可以用this调用一个构造器,但却不能调用两个。</li>
<li>this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。</li>
<li>this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。</li>
<li>从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。</li>
</ul>
<h4><a id="static_425"></a>static存在的主要意义</h4>
<p>static的主要意义是在于创建独立于具体对象的域变量或者方法。<strong>以致于即使没有创建对象,也能使用属性和调用方法</strong>!</p>
<p>static关键字还有一个比较关键的作用就是 <strong>用来形成静态代码块以优化程序性能</strong>。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。</p>
<p>为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。</p>
<h4><a id="static_435"></a>static的独特之处</h4>
<p>1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法<strong>不属于任何一个实例对象,而是被类的实例对象所共享</strong>。</p>
<blockquote>
<p>怎么理解 “被类的实例对象所共享” 这句话呢?就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我觉得我已经讲的很通俗了,你明白了咩?</p>
</blockquote>
<p>2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。</p>
<p>3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!</p>
<p>4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。</p>
<h4><a id="static_449"></a>static应用场景</h4>
<p>因为static是被类的实例对象所共享,因此如果<strong>某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量</strong>。</p>
<p>因此比较常见的static应用场景有:</p>
<blockquote>
<p>1、修饰成员变量 2、修饰成员方法 3、静态代码块 4、修饰类【只能修饰内部类也就是静态内部类】 5、静态导包</p>
</blockquote>
<h4><a id="static_459"></a>static注意事项</h4>
<p>1、静态只能访问静态。 2、非静态既可以访问非静态的,也可以访问静态的。</p>
<h3><a name="t20"></a><a name="t20"></a><a id="_465"></a>流程控制语句</h3>
<h4><a id="break_continue_return__467"></a>break ,continue ,return 的区别及作用</h4>
<p>break 跳出总上一层循环,不再执行循环(结束当前的循环体)</p>
<p>continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)</p>
<p>return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)</p>
<h4><a id="_Java__477"></a>在 Java 中,如何跳出当前的多重嵌套循环</h4>
<p>在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    ok<span class="token operator">:</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"i="</span> <span class="token operator">+</span> i <span class="token operator">+</span> <span class="token string">",j="</span> <span class="token operator">+</span> j<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>j <span class="token operator">==</span> <span class="token number">5</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">break</span> ok<span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li></ul></pre>
<h2><a name="t21"></a><a name="t21"></a><a id="_500"></a>面向对象</h2>
<h3><a name="t22"></a><a name="t22"></a><a id="_502"></a>面向对象概述</h3>
<h4><a id="_504"></a>面向对象和面向过程的区别</h4>
<p><strong>面向过程</strong>:</p>
<p>优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。</p>
<p>缺点:没有面向对象易维护、易复用、易扩展</p>
<p><strong>面向对象</strong>:</p>
<p>优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护</p>
<p>缺点:性能比面向过程低</p>
<p><strong>面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。</strong></p>
<p><strong>面向对象是模型化的,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。</strong></p>
<p>面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象了。</p>
<h3><a name="t23"></a><a name="t23"></a><a id="_528"></a>面向对象三大特性</h3>
<h4><a id="_530"></a>面向对象的特征有哪些方面</h4>
<p><strong>面向对象的特征主要有以下几个方面</strong>:</p>
<p><strong>抽象</strong>:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。</p>
<p>封装</p>
<p>封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。</p>
<p>继承</p>
<p>继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。</p>
<p>关于继承如下 3 点请记住:</p>
<ol>
<li>
<p>子类拥有父类非 private 的属性和方法。</p>
</li>
<li>
<p>子类可以拥有自己属性和方法,即子类可以对父类进行扩展。</p>
</li>
<li>
<p>子类可以用自己的方式实现父类的方法。(以后介绍)。</p>
</li>
</ol>
<p>多态</p>
<p>所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。</p>
<p>在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。</p>
<p>其中Java 面向对象编程三大特性:封装 继承 多态</p>
<p><strong>封装</strong>:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。</p>
<p><strong>继承</strong>:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承可以提高代码复用性。继承是多态的前提。</p>
<p><strong>关于继承如下 3 点请记住</strong>:</p>
<ol>
<li>
<p>子类拥有父类非 private 的属性和方法。</p>
</li>
<li>
<p>子类可以拥有自己属性和方法,即子类可以对父类进行扩展。</p>
</li>
<li>
<p>子类可以用自己的方式实现父类的方法。</p>
</li>
</ol>
<p><strong>多态性</strong>:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。</p>
<p>在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。</p>
<p>方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。</p>
<p>一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:</p>
<ul>
<li>方法重写(子类继承父类并重写父类中已有的或抽象的方法);</li>
<li>对象造型(用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。</li>
</ul>
<h4><a id="Java_593"></a>什么是多态机制?Java语言是如何实现多态的?</h4>
<p>所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。</p>
<p>多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。</p>
<p><strong>多态的实现</strong></p>
<p>Java实现多态有三个必要条件:继承、重写、向上转型。</p>
<p>继承:在多态中必须存在有继承关系的子类和父类。</p>
<p>重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。</p>
<p>向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。</p>
<p>只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。</p>
<p>对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。</p>
<h4><a id="_619"></a>面向对象五大基本原则是什么(可选)</h4>
<ul>
<li>单一职责原则SRP(Single Responsibility Principle)<br>
类的功能要单一,不能包罗万象,跟杂货铺似的。</li>
<li>开放封闭原则OCP(Open-Close Principle)<br>
一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。</li>
<li>里式替换原则LSP(the Liskov Substitution Principle LSP)<br>
子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~</li>
<li>依赖倒置原则DIP(the Dependency Inversion Principle DIP)<br>
高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。</li>
<li>接口分离原则ISP(the Interface Segregation Principle ISP)<br>
设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。</li>
</ul>
<h3><a name="t24"></a><a name="t24"></a><a id="_634"></a>类与接口</h3>
<h4><a id="_636"></a>抽象类和接口的对比</h4>
<p>抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。</p>
<p>从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。</p>
<p><strong>相同点</strong></p>
<ul>
<li>接口和抽象类都不能实例化</li>
<li>都位于继承的顶端,用于被其他实现或继承</li>
<li>都包含抽象方法,其子类都必须覆写这些抽象方法</li>
</ul>
<p><strong>不同点</strong></p>

<div class="table-box"><table>
<thead>
<tr>
<th>参数</th>
<th>抽象类</th>
<th>接口</th>
</tr>
</thead>
<tbody>
<tr>
<td>声明</td>
<td>抽象类使用abstract关键字声明</td>
<td>接口使用interface关键字声明</td>
</tr>
<tr>
<td>实现</td>
<td>子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现</td>
<td>子类使用implements关键字来实现接口。它需要提供接口中所有声明的方法的实现</td>
</tr>
<tr>
<td>构造器</td>
<td>抽象类可以有构造器</td>
<td>接口不能有构造器</td>
</tr>
<tr>
<td>访问修饰符</td>
<td>抽象类中的方法可以是任意访问修饰符</td>
<td>接口方法默认修饰符是public。并且不允许定义为 private 或者 protected</td>
</tr>
<tr>
<td>多继承</td>
<td>一个类最多只能继承一个抽象类</td>
<td>一个类可以实现多个接口</td>
</tr>
<tr>
<td>字段声明</td>
<td>抽象类的字段声明可以是任意的</td>
<td>接口的字段默认都是 static 和 final 的</td>
</tr>
</tbody>
</table></div><p><strong>备注</strong>:Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。</p>
<p>现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它。</p>
<p>接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:</p>
<ul>
<li>行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。</li>
<li>选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。</li>
</ul>
<h4><a id="_672"></a>普通类和抽象类有哪些区别?</h4>
<ul>
<li>普通类不能包含抽象方法,抽象类可以包含抽象方法。</li>
<li>抽象类不能直接实例化,普通类可以直接实例化。</li>
</ul>
<h4><a id="_final__679"></a>抽象类能使用 final 修饰吗?</h4>
<p>不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类</p>
<h4><a id="_685"></a>创建一个对象用什么关键字?对象实例与对象引用有何不同?</h4>
<p>new关键字,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)</p>
<h3><a name="t25"></a><a name="t25"></a><a id="_691"></a>变量与方法</h3>
<h4><a id="_693"></a>成员变量与局部变量的区别有哪些</h4>
<p>变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域</p>
<p>成员变量:方法外部,类内部定义的变量</p>
<p>局部变量:类的方法中的变量。</p>
<p>成员变量和局部变量的区别</p>
<p><strong>作用域</strong></p>
<p>成员变量:针对整个类有效。<br>
局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)</p>
<p><strong>存储位置</strong></p>
<p>成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。<br>
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放。</p>
<p><strong>生命周期</strong></p>
<p>成员变量:随着对象的创建而存在,随着对象的消失而消失<br>
局部变量:当方法调用完,或者语句结束后,就自动释放。</p>
<p><strong>初始值</strong></p>
<p>成员变量:有默认初始值。</p>
<p>局部变量:没有默认初始值,使用前必须赋值。</p>
<p>使用原则</p>
<p>在使用变量时需要遵循的原则为:就近原则<br>
首先在局部范围找,有就使用;接着在成员位置找。</p>
<h4><a id="Java_733"></a>在Java中定义一个不做事且没有参数的构造方法的作用</h4>
<p>Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。</p>
<h4><a id="_739"></a>在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?</h4>
<p>帮助子类做初始化工作。</p>
<h4><a id="_745"></a>一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?</h4>
<p>主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。</p>
<h4><a id="_751"></a>构造方法有哪些特性?</h4>
<p>名字与类名相同;</p>
<p>没有返回值,但不能用void声明构造函数;</p>
<p>生成类的对象时自动执行,无需调用。</p>
<h4><a id="_761"></a>静态变量和实例变量区别</h4>
<p>静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。</p>
<p>实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。</p>
<h4><a id="_769"></a>静态变量与普通变量区别</h4>
<p>static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。</p>
<p>还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。</p>
<h4><a id="_777"></a>静态方法和实例方法有何不同?</h4>
<p>静态方法和实例方法的区别主要体现在两个方面:</p>
<ol>
<li>在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。</li>
<li>静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制</li>
</ol>
<h4><a id="_786"></a>在一个静态方法内调用一个非静态成员为什么是非法的?</h4>
<p>由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。</p>
<h4><a id="_792"></a>什么是方法的返回值?返回值的作用是什么?</h4>
<p>方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!</p>
<h3><a name="t26"></a><a name="t26"></a><a id="_798"></a>内部类</h3>
<h4><a id="_800"></a>什么是内部类?</h4>
<p>在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是<strong>内部类</strong>。内部类本身就是类的一个属性,与其他属性定义方式一致。</p>
<h4><a id="_806"></a>内部类的分类有哪些</h4>
<p>内部类可以分为四种:<strong>成员内部类、局部内部类、匿名内部类和静态内部类</strong>。</p>
<h5><a id="_810"></a>静态内部类</h5>
<p>定义在类内部的静态类,就是静态内部类。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">int</span> radius <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>

    <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">StaticInner</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">visit</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"visit outer static  variable:"</span> <span class="token operator">+</span> radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li></ul></pre>
<p>静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;静态内部类的创建方式,<code>new 外部类.静态内部类()</code>,如下:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">Outer<span class="token punctuation">.</span>StaticInner inner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Outer<span class="token punctuation">.</span>StaticInner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
inner<span class="token punctuation">.</span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li></ul></pre>
<h5><a id="_834"></a>成员内部类</h5>
<p>定义在类内部,成员位置上的非静态类,就是成员内部类。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span>  <span class="token keyword">int</span> radius <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> count <span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">;</span>
    
     <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">visit</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"visit outer static  variable:"</span> <span class="token operator">+</span> radius<span class="token punctuation">)</span><span class="token punctuation">;</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"visit outer   variable:"</span> <span class="token operator">+</span> count<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li></ul></pre>
<p>成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有。成员内部类依赖于外部类的实例,它的创建方式<code>外部类实例.new 内部类()</code>,如下:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">Outer outer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Outer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Outer<span class="token punctuation">.</span>Inner inner <span class="token operator">=</span> outer<span class="token punctuation">.</span><span class="token keyword">new</span> <span class="token class-name">Inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
inner<span class="token punctuation">.</span><span class="token function">visit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li></ul></pre>
<h5><a id="_861"></a>局部内部类</h5>
<p>定义在方法中的内部类,就是局部内部类。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span>  <span class="token keyword">int</span> out_a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">int</span> STATIC_b <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testFunctionClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">int</span> inner_c <span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">;</span>
        <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
            <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>out_a<span class="token punctuation">)</span><span class="token punctuation">;</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>STATIC_b<span class="token punctuation">)</span><span class="token punctuation">;</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>inner_c<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
        Inner  inner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        inner<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">testStaticFunctionClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">int</span> d <span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">;</span>
        <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
            <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                <span class="token comment">// System.out.println(out_a); 编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>STATIC_b<span class="token punctuation">)</span><span class="token punctuation">;</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>d<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
        Inner  inner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        inner<span class="token punctuation">.</span><span class="token function">fun</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">19</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">20</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">21</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">22</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">23</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">24</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">25</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">26</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">27</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">28</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">29</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">30</li></ul></pre>
<p>定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部内部类的创建方式,在对应方法内,<code>new 内部类()</code>,如下:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"> <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">testStaticFunctionClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>
    Inner  inner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 <span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li></ul></pre>
<h5><a id="_908"></a>匿名内部类</h5>
<p>匿名内部类就是没有名字的内部类,日常开发中使用的比较多。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token keyword">int</span> i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">new</span> <span class="token class-name">Service</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> i<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"匿名内部类"</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
 <span class="token punctuation">}</span>
 <span class="token comment">//匿名内部类必须继承或实现一个已有的接口 </span>
 <span class="token keyword">interface</span> <span class="token class-name">Service</span><span class="token punctuation">{</span>
    <span class="token keyword">void</span> <span class="token function">method</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li></ul></pre>
<p>除了没有名字,匿名内部类还有以下特点:</p>
<ul>
<li>匿名内部类必须继承一个抽象类或者实现一个接口。</li>
<li>匿名内部类不能定义任何静态成员和静态方法。</li>
<li>当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。</li>
<li>匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。</li>
</ul>
<p>匿名内部类创建方式:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">new</span> 类<span class="token operator">/</span>接口<span class="token punctuation">{</span> 
  <span class="token comment">//匿名内部类实现部分</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li></ul></pre>
<h4><a id="_948"></a>内部类的优点</h4>
<p>我们为什么要使用内部类呢?因为它有以下优点:</p>
<ul>
<li>一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!</li>
<li>内部类不为同一包的其他类所见,具有很好的封装性;</li>
<li>内部类有效实现了“多重继承”,优化 java 单继承的缺陷。</li>
<li>匿名内部类可以很方便的定义回调。</li>
</ul>
<h4><a id="_959"></a>内部类有哪些应用场景</h4>
<ol>
<li>一些多算法场合</li>
<li>解决一些非面向对象的语句块。</li>
<li>适当使用内部类,使得代码更加灵活和富有扩展性。</li>
<li>当某个类除了它的外部类,不再被其他的类使用时。</li>
</ol>
<h4><a id="final_968"></a>局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?</h4>
<p>局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final呢?它内部原理是什么呢?</p>
<p>先看这段代码:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>

    <span class="token keyword">void</span> <span class="token function">outMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">final</span> <span class="token keyword">int</span> a <span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">;</span>
        <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
            <span class="token keyword">void</span> <span class="token function">innerMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li></ul></pre>
<p>以上例子,为什么要加final呢?是因为<strong>生命周期不一致</strong>, 局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。</p>
<h4><a id="_993"></a>内部类相关,看程序说出运行结果</h4>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Outer</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> age <span class="token operator">=</span> <span class="token number">12</span><span class="token punctuation">;</span>

    <span class="token keyword">class</span> <span class="token class-name">Inner</span> <span class="token punctuation">{</span>
        <span class="token keyword">private</span> <span class="token keyword">int</span> age <span class="token operator">=</span> <span class="token number">13</span><span class="token punctuation">;</span>
        <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">int</span> age <span class="token operator">=</span> <span class="token number">14</span><span class="token punctuation">;</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"局部变量:"</span> <span class="token operator">+</span> age<span class="token punctuation">)</span><span class="token punctuation">;</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"内部类变量:"</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"外部类变量:"</span> <span class="token operator">+</span> Outer<span class="token punctuation">.</span><span class="token keyword">this</span><span class="token punctuation">.</span>age<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Outer<span class="token punctuation">.</span>Inner in <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Outer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">new</span> <span class="token class-name">Inner</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        in<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">19</li></ul></pre>
<p>运行结果:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">局部变量:<span class="token number">14</span>
内部类变量:<span class="token number">13</span>
外部类变量:<span class="token number">12</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li></ul></pre>
<h3><a name="t27"></a><a name="t27"></a><a id="_1027"></a>重写与重载</h3>
<h4><a id="constructoroverride_1029"></a>构造器(constructor)是否可被重写(override)</h4>
<p>构造器不能被继承,因此不能被重写,但可以被重载。</p>
<h4><a id="OverloadOverride_1035"></a>重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?</h4>
<p>方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。</p>
<p>重载:发生在同一个类中,方法名相同参数列表不同(参数类型不同、个数不同、顺序不同),与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分</p>
<p>重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为private则子类中就不是重写。</p>
<h3><a name="t28"></a><a name="t28"></a><a id="_1045"></a>对象相等判断</h3>
<h4><a id="__equals__1047"></a>== 和 equals 的区别是什么</h4>
<p><strong>==</strong> : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)</p>
<p><strong>equals()</strong> : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:</p>
<p>情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。</p>
<p>情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。</p>
<p><strong>举个例子:</strong></p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">test1</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        String a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"ab"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// a 为一个引用</span>
        String b <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"ab"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// b为另一个引用,对象的内容一样</span>
        String aa <span class="token operator">=</span> <span class="token string">"ab"</span><span class="token punctuation">;</span> <span class="token comment">// 放在常量池中</span>
        String bb <span class="token operator">=</span> <span class="token string">"ab"</span><span class="token punctuation">;</span> <span class="token comment">// 从常量池中查找</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>aa <span class="token operator">==</span> bb<span class="token punctuation">)</span> <span class="token comment">// true</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"aa==bb"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span> <span class="token comment">// false,非同一对象</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"a==b"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"aEQb"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token number">42</span> <span class="token operator">==</span> <span class="token number">42.0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// true</span>
            System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"true"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li></ul></pre>
<p><strong>说明:</strong></p>
<ul>
<li>String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。</li>
<li>当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。</li>
</ul>
<h4><a id="hashCode__equals__1086"></a>hashCode 与 equals (重要)</h4>
<p>HashSet如何检查重复</p>
<p>两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?</p>
<p>hashCode和equals方法的关系</p>
<p>面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”</p>
<p><strong>hashCode()介绍</strong></p>
<p>hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。</p>
<p>散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)</p>
<p><strong>为什么要有 hashCode</strong></p>
<p><strong>我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode</strong>:</p>
<p>当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head first java》第二版)。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。</p>
<p><strong>hashCode()与equals()的相关规定</strong></p>
<p>如果两个对象相等,则hashcode一定也是相同的</p>
<p>两个对象相等,对两个对象分别调用equals方法都返回true</p>
<p>两个对象有相同的hashcode值,它们也不一定是相等的</p>
<p><strong>因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖</strong></p>
<p>hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)</p>
<h4><a id="_1126"></a>对象的相等与指向他们的引用相等,两者有什么不同?</h4>
<p>对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。</p>
<h3><a name="t29"></a><a name="t29"></a><a id="_1132"></a>值传递</h3>
<h4><a id="_1134"></a>当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递</h4>
<p>是值传递。Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的</p>
<h4><a id="_Java__1140"></a>为什么 Java 中只有值传递</h4>
<p>首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。<strong>按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。</strong>  它用来描述各种程序设计语言(不只是Java)中方法参数传递方式。</p>
<p><strong>Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。</strong></p>
<p><strong>下面通过 3 个例子来给大家说明</strong></p>
<p>example 1</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> num1 <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
    <span class="token keyword">int</span> num2 <span class="token operator">=</span> <span class="token number">20</span><span class="token punctuation">;</span>

    <span class="token function">swap</span><span class="token punctuation">(</span>num1<span class="token punctuation">,</span> num2<span class="token punctuation">)</span><span class="token punctuation">;</span>

    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"num1 = "</span> <span class="token operator">+</span> num1<span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"num2 = "</span> <span class="token operator">+</span> num2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">swap</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span> <span class="token keyword">int</span> b<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">int</span> temp <span class="token operator">=</span> a<span class="token punctuation">;</span>
    a <span class="token operator">=</span> b<span class="token punctuation">;</span>
    b <span class="token operator">=</span> temp<span class="token punctuation">;</span>

    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"a = "</span> <span class="token operator">+</span> a<span class="token punctuation">)</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"b = "</span> <span class="token operator">+</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li></ul></pre>
<p><strong>结果</strong>:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">a <span class="token operator">=</span> <span class="token number">20</span>
b <span class="token operator">=</span> <span class="token number">10</span>
num1 <span class="token operator">=</span> <span class="token number">10</span>
num2 <span class="token operator">=</span> <span class="token number">20</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li></ul></pre>
<p><strong>解析</strong>:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xNDAyMzk3Mi00ZWQyZjQ0NTlmN2MyYzkwLmpwZw?x-oss-process=image/format,png" alt="img"></p>
<p>在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。</p>
<p><strong>通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看 example2.</strong></p>
<p>example 2</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> arr <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">change</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">change</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> array<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// 将数组的第一个元素变为0</span>
        array<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li></ul></pre>
<p><strong>结果</strong>:</p>
<pre class="prettyprint"><code class="prism language-undefined has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">1
0
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li></ul></pre>
<p><strong>解析</strong>:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xNDAyMzk3Mi1kYWI5Mzg5ZWRmMjIxNmIzLmpwZw?x-oss-process=image/format,png" alt="img"></p>
<p>array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。</p>
<p><strong>通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。</strong></p>
<p><strong>很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员(甚至本书的作者)认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题。</strong></p>
<p>example 3</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">// TODO Auto-generated method stub</span>
        Student s1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Student</span><span class="token punctuation">(</span><span class="token string">"小张"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Student s2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Student</span><span class="token punctuation">(</span><span class="token string">"小李"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Test<span class="token punctuation">.</span><span class="token function">swap</span><span class="token punctuation">(</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"s1:"</span> <span class="token operator">+</span> s1<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"s2:"</span> <span class="token operator">+</span> s2<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">swap</span><span class="token punctuation">(</span>Student x<span class="token punctuation">,</span> Student y<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        Student temp <span class="token operator">=</span> x<span class="token punctuation">;</span>
        x <span class="token operator">=</span> y<span class="token punctuation">;</span>
        y <span class="token operator">=</span> temp<span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"x:"</span> <span class="token operator">+</span> x<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"y:"</span> <span class="token operator">+</span> y<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">19</li></ul></pre>
<p><strong>结果</strong>:</p>
<pre class="prettyprint"><code class="prism language-undefined has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">x:小李
y:小张
s1:小张
s2:小李
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li></ul></pre>
<p><strong>解析</strong>:</p>
<p>交换之前:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xNDAyMzk3Mi03MmIwYzFmYjlmM2IwNzc2LmpwZw?x-oss-process=image/format,png" alt="img"></p>
<p>交换之后:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xNDAyMzk3Mi0zYWUzNzY4NGNiMzg2Njc4LmpwZw?x-oss-process=image/format,png" alt="img"></p>
<p>通过上面两张图可以很清晰的看出: <strong>方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝</strong></p>
<p><strong>总结</strong></p>
<p>Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。</p>
<p>下面再总结一下Java中方法参数的使用情况:</p>
<ul>
<li>一个方法不能修改一个基本数据类型的参数(即数值型或布尔型》</li>
<li>一个方法可以改变一个对象参数的状态。</li>
<li>一个方法不能让对象参数引用一个新的对象。</li>
</ul>
<h4><a id="_1286"></a>值传递和引用传递有什么区别</h4>
<p>值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。</p>
<p>引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。</p>
<h3><a name="t30"></a><a name="t30"></a><a id="Java_1294"></a>Java包</h3>
<h4><a id="JDK__1296"></a>JDK 中常用的包有哪些</h4>
<ul>
<li>java.lang:这个是系统的基础类;</li>
<li>java.io:这里面是所有输入输出有关的类,比如文件操作等;</li>
<li>java.nio:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包;</li>
<li>java.net:这里面是与网络有关的类;</li>
<li>java.util:这个是系统辅助类,特别是集合类;</li>
<li>java.sql:这个是数据库操作的类。</li>
</ul>
<h4><a id="import_javajavax_1307"></a>import java和javax有什么区别</h4>
<p>刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移,javax 逐渐的扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包将是太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准API的一部分。</p>
<p>所以,实际上java和javax没有区别。这都是一个名字。</p>
<h2><a name="t31"></a><a name="t31"></a><a id="IO_1317"></a>IO流</h2>
<h3><a name="t32"></a><a name="t32"></a><a id="java__IO__1319"></a>java 中 IO 流分为几种?</h3>
<ul>
<li>按照流的流向分,可以分为输入流和输出流;</li>
<li>按照操作单元划分,可以划分为字节流和字符流;</li>
<li>按照流的角色划分为节点流和处理流。</li>
</ul>
<p>Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。</p>
<ul>
<li>InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。</li>
<li>OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。</li>
</ul>
<p>按操作方式分类结构图:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teS1ibG9nLXRvLXVzZS5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vMjAxOS02L0lPLSVFNiU5MyU4RCVFNCVCRCU5QyVFNiU5NiVCOSVFNSVCQyU4RiVFNSU4OCU4NiVFNyVCMSVCQi5wbmc?x-oss-process=image/format,png" alt="IO-操作方式分类"></p>
<p>按操作对象分类结构图:</p>
<p><img src="https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teS1ibG9nLXRvLXVzZS5vc3MtY24tYmVpamluZy5hbGl5dW5jcy5jb20vMjAxOS02L0lPLSVFNiU5MyU4RCVFNCVCRCU5QyVFNSVBRiVCOSVFOCVCMSVBMSVFNSU4OCU4NiVFNyVCMSVCQi5wbmc?x-oss-process=image/format,png" alt="IO-操作对象分类"></p>
<h3><a name="t33"></a><a name="t33"></a><a id="BIONIOAIO__1341"></a>BIO,NIO,AIO 有什么区别?</h3>
<p>简答</p>
<ul>
<li>BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。</li>
<li>NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。</li>
<li>AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。</li>
</ul>
<p>详细回答</p>
<ul>
<li><strong>BIO (Blocking I/O):</strong> 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。</li>
<li><strong>NIO (New I/O):</strong> NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。 NIO提供了与传统BIO模型中的 <code>Socket</code> 和 <code>ServerSocket</code> 相对应的 <code>SocketChannel</code> 和 <code>ServerSocketChannel</code> 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发</li>
<li><strong>AIO (Asynchronous I/O):</strong> AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。</li>
</ul>
<h3><a name="t34"></a><a name="t34"></a><a id="Files_1357"></a>Files的常用方法都有哪些?</h3>
<ul>
<li>Files. exists():检测文件路径是否存在。</li>
<li>Files. createFile():创建文件。</li>
<li>Files. createDirectory():创建文件夹。</li>
<li>Files. delete():删除一个文件或目录。</li>
<li>Files. copy():复制文件。</li>
<li>Files. move():移动文件。</li>
<li>Files. size():查看文件个数。</li>
<li>Files. read():读取文件。</li>
<li>Files. write():写入文件。</li>
</ul>
<h2><a name="t35"></a><a name="t35"></a><a id="_1371"></a>反射</h2>
<h3><a name="t36"></a><a name="t36"></a><a id="_1373"></a>什么是反射机制?</h3>
<p>JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。</p>
<p>静态编译和动态编译</p>
<ul>
<li>**静态编译:**在编译时确定类型,绑定对象</li>
<li>**动态编译:**运行时确定类型,绑定对象</li>
</ul>
<h3><a name="t37"></a><a name="t37"></a><a id="_1384"></a>反射机制优缺点</h3>
<ul>
<li><strong>优点:</strong> 运行期类型的判断,动态加载类,提高代码灵活度。</li>
<li><strong>缺点:</strong> 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。</li>
</ul>
<h3><a name="t38"></a><a name="t38"></a><a id="_1391"></a>反射机制的应用场景有哪些?</h3>
<p>反射是框架设计的灵魂。</p>
<p>在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。</p>
<p>举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这个字符串获得某个类的Class实例; 4)动态配置实例的属性</p>
<h3><a name="t39"></a><a name="t39"></a><a id="Java_1401"></a>Java获取反射的三种方法</h3>
<p>1.通过new对象实现反射机制 2.通过路径实现反射机制 3.通过类名实现反射机制</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Student</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">int</span> id<span class="token punctuation">;</span>
    String name<span class="token punctuation">;</span>
    <span class="token keyword">protected</span> <span class="token keyword">boolean</span> sex<span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">float</span> score<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li></ul></pre>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Get</span> <span class="token punctuation">{</span>
    <span class="token comment">//获取反射机制三种方式</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> ClassNotFoundException <span class="token punctuation">{</span>
        <span class="token comment">//方式一(通过建立对象)</span>
        Student stu <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Student</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Class <span class="token class-name">classobj1</span> <span class="token operator">=</span> stu<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>classobj1<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">//方式二(所在通过路径-相对路径)</span>
        Class <span class="token class-name">classobj2</span> <span class="token operator">=</span> Class<span class="token punctuation">.</span><span class="token function">forName</span><span class="token punctuation">(</span><span class="token string">"fanshe.Student"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>classobj2<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token comment">//方式三(通过类名)</span>
        Class <span class="token class-name">classobj3</span> <span class="token operator">=</span> Student<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">;</span>
        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>classobj3<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li></ul></pre>
<h2><a name="t40"></a><a name="t40"></a><a id="_1436"></a>网络编程</h2>
<p>网络编程的面试题可以查看我的这篇文章<a href="https://blog.csdn.net/ThinkWon/article/details/104903925">重学TCP/IP协议和三次握手四次挥手</a>,内容不仅包括TCP/IP协议和三次握手四次挥手的知识,还包括计算机网络体系结构,HTTP协议,get请求和post请求区别,session和cookie的区别等,欢迎大家阅读。</p>
<h2><a name="t41"></a><a name="t41"></a><a id="API_1442"></a>常用API</h2>
<h3><a name="t42"></a><a name="t42"></a><a id="String_1444"></a>String相关</h3>
<h4><a id="_1446"></a>字符型常量和字符串常量的区别</h4>
<ol>
<li>形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符</li>
<li>含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)</li>
<li>占内存大小 字符常量只占一个字节 字符串常量占若干个字节(至少一个字符结束标志)</li>
</ol>
<h4><a id="_1454"></a>什么是字符串常量池?</h4>
<p>字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。</p>
<h4><a id="String__1460"></a>String 是最基本的数据类型吗</h4>
<p>不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。</p>
<p>这是很基础的东西,但是很多初学者却容易忽视,Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};</p>
<p>但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。</p>
<h4><a id="String_1470"></a>String有哪些特性</h4>
<ul>
<li>
<p>不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。</p>
</li>
<li>
<p>常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。</p>
</li>
<li>
<p>final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。</p>
</li>
</ul>
<h4><a id="String_1480"></a>String为什么是不可变的吗?</h4>
<p>简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下图所以:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">/** The value is used for character storage. */</span>
<span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token keyword">char</span> value<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li></ul></pre>
<h4><a id="String_1491"></a>String真的是不可变的吗?</h4>
<p>我觉得如果别人问这个问题的话,回答不可变就可以了。 下面只是给大家看两个有代表性的例子:</p>
<p><strong>1) String不可变但不代表引用不可以变</strong></p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">String str <span class="token operator">=</span> <span class="token string">"Hello"</span><span class="token punctuation">;</span>
str <span class="token operator">=</span> str <span class="token operator">+</span> <span class="token string">" World"</span><span class="token punctuation">;</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"str="</span> <span class="token operator">+</span> str<span class="token punctuation">)</span><span class="token punctuation">;</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li></ul></pre>
<p>结果:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">str<span class="token operator">=</span>Hello World
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li></ul></pre>
<p>解析:</p>
<p>实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。</p>
<p><strong>2) 通过反射是可以修改所谓的“不可变”对象</strong></p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token comment">// 创建字符串"Hello World", 并赋给引用s</span>
String s <span class="token operator">=</span> <span class="token string">"Hello World"</span><span class="token punctuation">;</span>

System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"s = "</span> <span class="token operator">+</span> s<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Hello World</span>

<span class="token comment">// 获取String类中的value字段</span>
Field valueFieldOfString <span class="token operator">=</span> String<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">.</span><span class="token function">getDeclaredField</span><span class="token punctuation">(</span><span class="token string">"value"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 改变value属性的访问权限</span>
valueFieldOfString<span class="token punctuation">.</span><span class="token function">setAccessible</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 获取s对象上的value属性的值</span>
<span class="token keyword">char</span><span class="token punctuation">[</span><span class="token punctuation">]</span> value <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">char</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span> valueFieldOfString<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 改变value所引用的数组中的第5个字符</span>
value<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'_'</span><span class="token punctuation">;</span>

System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"s = "</span> <span class="token operator">+</span> s<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Hello_World</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">17</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">18</li></ul></pre>
<p>结果:</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">s <span class="token operator">=</span> Hello World
s <span class="token operator">=</span> Hello_World
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li></ul></pre>
<p>解析:</p>
<p>用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。</p>
<h4><a id="_String__1549"></a>是否可以继承 String 类</h4>
<p>String 类是 final 类,不可以被继承。</p>
<h4><a id="String_stri_String_strnew_Stringi_1555"></a>String str="i"与 String str=new String(“i”)一样吗?</h4>
<p>不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。</p>
<h4><a id="String_s__new_Stringxyz_1561"></a>String s = new String(“xyz”);创建了几个字符串对象</h4>
<p>两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">String str1 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span> <span class="token comment">//str1指向静态区</span>
String str2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">//str2指向堆上的对象</span>
String str3 <span class="token operator">=</span> <span class="token string">"hello"</span><span class="token punctuation">;</span>
String str4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>str2<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str2<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>str4<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str3<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str2 <span class="token operator">==</span> str4<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str2 <span class="token operator">==</span> <span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>
str2 <span class="token operator">=</span> str1<span class="token punctuation">;</span>
System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>str2 <span class="token operator">==</span> <span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//true</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li></ul></pre>
<h4><a id="_1582"></a>如何将字符串反转?</h4>
<p>使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。</p>
<p>示例代码:</p>
<pre class="prettyprint"><code class="prism language-Java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;">// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li></ul></pre>
<h4><a id="_lengthString__length_1601"></a>数组有没有 length()方法?String 有没有 length()方法</h4>
<p>数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。</p>
<h4><a id="String__1607"></a>String 类的常用方法都有那些?</h4>
<ul>
<li>indexOf():返回指定字符的索引。</li>
<li>charAt():返回指定索引处的字符。</li>
<li>replace():字符串替换。</li>
<li>trim():去除字符串两端空白。</li>
<li>split():分割字符串,返回一个分割后的字符串数组。</li>
<li>getBytes():返回字符串的 byte 类型数组。</li>
<li>length():返回字符串长度。</li>
<li>toLowerCase():将字符串转成小写字母。</li>
<li>toUpperCase():将字符串转成大写字符。</li>
<li>substring():截取字符串。</li>
<li>equals():字符串比较。</li>
</ul>
<h4><a id="_HashMap__String__key__1623"></a>在使用 HashMap 的时候,用 String 做 key 有什么好处?</h4>
<p>HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。</p>
<h4><a id="StringStringBufferStringBuilderString_1629"></a>String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的</h4>
<p><strong>可变性</strong></p>
<p>String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。</p>
<p><strong>线程安全性</strong></p>
<p>String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。</p>
<p><strong>性能</strong></p>
<p>每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。</p>
<p><strong>对于三者使用的总结</strong></p>
<p>如果要操作少量的数据用 = String</p>
<p>单线程操作字符串缓冲区 下操作大量数据 = StringBuilder</p>
<p>多线程操作字符串缓冲区 下操作大量数据 = StringBuffer</p>
<h3><a name="t43"></a><a name="t43"></a><a id="Date_1655"></a>Date相关</h3>
<h3><a name="t44"></a><a name="t44"></a><a id="_1659"></a>包装类相关</h3>
<h4><a id="_1661"></a>自动装箱与拆箱</h4>
<p><strong>装箱</strong>:将基本类型用它们对应的引用类型包装起来;</p>
<p><strong>拆箱</strong>:将包装类型转换为基本数据类型;</p>
<h4><a id="int__Integer__1669"></a>int 和 Integer 有什么区别</h4>
<p>Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是 Integer,从 Java 5 开始引入了自动装箱/拆箱机制,使得二者可以相互转换。</p>
<p>Java 为每个原始类型提供了包装类型:</p>
<p>原始类型: boolean,char,byte,short,int,long,float,double</p>
<p>包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double</p>
<h4><a id="Integer_a_127__Integer_b__127_1681"></a>Integer a= 127 与 Integer b = 127相等吗</h4>
<p>对于对象引用类型:==比较的是对象的内存地址。<br>
对于基本数据类型:==比较的是值。</p>
<p>如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false</p>
<pre class="prettyprint"><code class="prism language-java has-numbering" onclick="mdcp.copyCode(event)" style="position: unset;"><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span>String<span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Integer a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Integer b <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>  <span class="token comment">// 将3自动装箱成Integer类型</span>
    <span class="token keyword">int</span> c <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false 两个引用没有引用同一对象</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> c<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true a自动拆箱成int类型再和c比较</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>b <span class="token operator">==</span> c<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>

    Integer a1 <span class="token operator">=</span> <span class="token number">128</span><span class="token punctuation">;</span>
    Integer b1 <span class="token operator">=</span> <span class="token number">128</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>a1 <span class="token operator">==</span> b1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>

    Integer a2 <span class="token operator">=</span> <span class="token number">127</span><span class="token punctuation">;</span>
    Integer b2 <span class="token operator">=</span> <span class="token number">127</span><span class="token punctuation">;</span>
    System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>a2 <span class="token operator">==</span> b2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>
<span class="token punctuation">}</span>
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">1</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">2</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">3</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">4</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">5</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">6</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">7</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">8</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">9</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">10</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">11</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">12</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">13</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">14</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">15</li><li style="color: rgb(153, 153, 153); --darkreader-inline-color:#ddd4c8;" data-darkreader-inline-color="">16</li></ul></pre>
<h2><a name="t45"></a><a name="t45"></a><a id="_1709"></a>常用工具类库</h2>
<h2><a name="t46"></a><a name="t46"></a><a id="_1713"></a>单元测试</h2>
<h2><a name="t47"></a><a name="t47"></a><a id="_1717"></a>日志</h2>

                                    </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值