目录
- 201. 删除_你们怎么处理redis缓存的数据,怎么删除的
- 202. redis的事务
- 203. 什么是ES?
- 204. 为什么要使用到ES?
- 205. Elasticsearch是如何实现Master选举的?
- 206. Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
- 207. 客户端在和集群连接时,如何选择特定的节点执行请求的?
- 208. 详细描述一下Elasticsearch索引文档的过程。
- 209. 详细描述一下Elasticsearch更新和删除文档的过程。
- 210. 详细描述一下Elasticsearch搜索的过程。
- 211. 为什么使用索引工具查询快
- 212. es集群的脑裂问题
- 213. 详细描述一下Elasticsearch更新和删除文档的过程。
- 214. 在并发情况下,Elasticsearch如果保证读写一致?
- 215. 如何监控Elasticsearch集群状态?
- 216. Elasticsearch中的倒排索引是什么?
- 217. ElasticSearch中的分片是什么?
- 218. ElasticSearch中的副本是什么?
- 219. ElasticSearch中的分析器是什么?
- 220. 什么是ElasticSearch中的编译器?
- 221. Elasticsearch是如何实现高亮?
- 222. 如何实现搜索排名
- 223. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
- 224. Java有没有goto?
- 225. 说说&和&&的区别。
- 226. 在JAVA中如何跳出当前的多重嵌套循环?
- 227. switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
- 228. short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
- 229. char型变量中能不能存贮一个中文汉字?为什么?
- 230. 用最有效率的方法算出2乘以8等於几?
- 231. 请设计一个一百亿的计算器
- 232. 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
- 233. "=="和equals方法究竟有什么区别?
- 234. 静态变量和实例变量的区别?
- 235. 是否可以从一个static方法内部发出对非static方法的调用?
- 236. Integer与int的区别
- 237. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
- 238. 请说出作用域public,private,protected,以及不写时的区别
- 239. Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?
- 240. 构造器Constructor是否可被override?
- 241. 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?
- 242. 写clone()方法时,通常都有一行代码,是什么?
- 243. 面向对象的特征有哪些方面
- 244. java中实现多态的机制是什么?
- 245. abstract class和interface有什么区别?
- 246. abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
- 247. 什么是内部类?Static Nested Class 和 Inner Class的不同。
- 248. 内部类可以引用它的包含类的成员吗?有没有什么限制?
- 249. Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?
- 250. super.getClass()方法调用
- 251. String是最基本的数据类型吗?
- 252. String是最基本的数据类型吗?
- 253. String对象深入
- 254. 是否可以继承String类?
- 255. String s = new String("xyz");创建了几个String Object? 二者之间有什么区别?
- 256. String 和StringBuffer的区别
- 257. 如何把一段逗号分割的字符串转换成一个数组?
- 258. 下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
- 259. try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
- 260. 下面的程序代码输出的结果是多少?
- 261. final, finally, finalize的区别。
- 262. 运行时异常与一般异常有何异同?
- 263. error和exception有什么区别?
- 264. Java中的异常处理机制的简单原理和应用。
- 265. 请写出你最常见到的5个runtime exception。
- 266. java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?
- 267. sleep() 和 wait() 有什么区别?
- 268. 同步和异步有何异同,在什么情况下分别使用他们?举例说明。
- 269. 下面两个方法同步吗?(自己发明)
- 270. 多线程有几种实现方法?同步有几种实现方法?
- 271. 启动一个线程是用run()还是start()?
- 272. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
- 273. 线程的基本概念、线程的基本状态以及状态之间的关系
- 274. 简述synchronized和java.util.concurrent.locks.Lock的异同 ?
- 275. 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
- 276. 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。
- 277. 介绍Collection框架的结构
- 278. Collection框架中实现比较要实现什么接口
- 279. ArrayList和Vector的区别
- 280. HashMap和Hashtable的区别
- 281. List 和 Map 区别?
- 282. List, Set, Map是否继承自Collection接口?
- 283. List、Map、Set三个接口,存取元素时,各有什么特点?
- 284. 说出ArrayList,Vector, LinkedList的存储性能和特性
- 285. 去掉一个Vector集合中重复的元素
- 286. Collection 和 Collections的区别。
- 287. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?
- 288. 你所知道的集合类都有哪些?主要方法?
- 289. 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
- 290. TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!
- 291. 说出一些常用的类,包,接口,请各举5个
- 292. java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
- 293. 字节流与字符流的区别
- 294. 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- 295. 描述一下JVM加载class文件的原理机制?
- 296. heap和stack有什么区别。
- 297. GC是什么? 为什么要有GC?
- 298. 垃圾回收的优点和原理。并考虑2种回收机制。
- 299. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
- 300. 什么时候用assert。
201. 删除_你们怎么处理redis缓存的数据,怎么删除的
redis缓存的数据有一些是常驻缓存的,当数据库中数据有变化时做数据同步。
有一些缓存是设置有效期的,当缓存到期后会自动删除。删除redis缓存使用del或者hdel命令。[备注:hdel,hashKey delete]
202. redis的事务
- redis事务:可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞.
- redis事务能干嘛:一个队列中,一次性、顺序性、排他性的执行一系列命令.
[备注: ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)] - redis监控:锁的介绍
在MySQL中我们都知道有行锁和表锁的概念,所谓的行锁也就是把我需要改的那一行给锁住,不让其他的事务去修改;而表锁就是在修改一张表的时候把整张表都锁住,不让其他的事务修改,所以行锁的效率比表锁的概念更高,那么在redis也存在锁的概念- 乐观锁(Optimistic Lock): 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,乐观锁策略:提交版本必须大于记录当前版本才能执行更新
- 悲观锁(Pessimistic Lock): 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁.[备注: 在Java中,synchronized的思想也是悲观锁]
- CAS(Check And Set):
- redis事务三阶段:
- 开启:以MULTI开始一个事务
- 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
- 执行:由EXEC命令触发事务(execute,执行)
- redis事务三大特性:
- 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
- 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
203. 什么是ES?
es是一个高扩展、开源的全文检索和分析引擎,它可以准实时地快速存储、搜索、分析海量的数据。
204. 为什么要使用到ES?
因为在我们商城中的数据,将来会非常多,所以采用以往的模糊查询,模糊查询前置配置,会放弃索引,导致商品查询是全表扫面,在百万级别的数据库中,效率非常低下,而我们使用ES做一个全文索引,我们将经常查询的商品的某些字段,比如说商品名,描述、价格还有id这些字段我们放入我们索引库里,可以提高查询速度。
205. Elasticsearch是如何实现Master选举的?
- Elasticsearch的选主是ZenDiscovery模块负责的,主要包含Ping(节点之间通过这个RPC来发现彼此)和Unicast(单播模块包含一个主机列表以控制哪些节点需要ping通)这两部分;
- 对所有可以成为master的节点(node.master: true)根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
- 如果对某个节点的投票数达到一定的值(可以成为master节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。
补充:master节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data节点可以关闭http功能。
206. Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
- 当集群master候选数量不小于3个时,可以通过设置最少投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
- 当候选数量为两个时,只能修改为唯一的一个master候选,其他作为data节点,避免脑裂问题。
207. 客户端在和集群连接时,如何选择特定的节点执行请求的?
TransportClient利用transport模块远程连接一个elasticsearch集群。它并不加入到集群中,只是简单的获得一个或者多个初始化的transport地址,并以 轮询 的方式与这些地址进行通信。
208. 详细描述一下Elasticsearch索引文档的过程。
协调节点默认使用文档ID参与计算(也支持通过routing),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
- 当分片所在的节点接收到来自协调节点的请求后,会将请求写入到Memory Buffer,然后定时(默认是每隔1秒)写入到Filesystem Cache,这个从Momery Buffer到Filesystem Cache的过程就叫做refresh;
- 当然在某些情况下,存在Momery Buffer和Filesystem Cache的数据可能会丢失,ES是通过translog的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到translog中,当Filesystem cache中的数据写入到磁盘中时,才会清除掉,这个过程叫做flush;
- 在flush过程中,内存中的缓冲将被清除,内容被写入一个新段,段的fsync将创建一个新的提交点,并将内容刷新到磁盘,旧的translog将被删除并开始一个新的translog。
- flush触发的时机是定时触发(默认30分钟)或者translog变得太大(默认为512M)时;
补充:关于Lucene的Segement:- Lucene索引是由多个段组成,段本身是一个功能齐全的倒排索引。
- 段是不可变的,允许Lucene将新的文档增量地添加到索引中,而不用从头重建索引。
- 对于每一个搜索请求而言,索引中的所有段都会被搜索,并且每个段会消耗CPU的时钟周、文件句柄和内存。这意味着段的数量越多,搜索性能会越低。
- 为了解决这个问题,Elasticsearch会合并小段到一个较大的段,提交新的合并段到磁盘,并删除那些旧的小段。
209. 详细描述一下Elasticsearch更新和删除文档的过程。
- 删除和更新也都是写操作,但是Elasticsearch中的文档是不可变的,因此不能被删除或者改动以展示其变更;
- 磁盘上的每个段都有一个相应的.del文件。当删除请求发送后,文档并没有真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del文件中被标记为删除的文档将不会被写入新段。
- 在新的文档被创建时,Elasticsearch会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
210. 详细描述一下Elasticsearch搜索的过程。
- 搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
- 在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询Filesystem Cache的,但是有部分数据还在Memory Buffer,所以搜索是近实时的。
- 每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
- 接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
补充:
Query Then Fetch的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch增加了一个预查询的处理,询问Term和Document frequency,这个评分更准确,但是性能会变差。
211. 为什么使用索引工具查询快
(使用了倒排索引的技术,大致介绍一下倒排索引,还有索引库中的词都是按照顺序排列,后期根据一个关键词查询的时候,可以利用类似折半查找的算法,查询效率非常高)
使用了倒排索引的技术,一般我们都是这样定义id 关键词,倒排索引是关键词 id正好相反,使用索引工具进行查询时,首先得到关键词,建立倒排索引表,关键词----索引列表包含该关键词所在的文档的id、在该文档中出现的次数、在该文档中出现的位置信息,这种由属性值确定记录的位置的方式成为倒排索引。还有索引库中的词都是按照顺序排列 ,后期根据一个关键词查询的时候,可以利用类似折半查找的算法,查询效率非常高;
212. es集群的脑裂问题
es集群有可能会出现脑裂问题,原因主要有两个:
- 如果集群中节点不在同一个网段有可能是网络延迟造成的
- 如果集群中的节点在同一个网段,有可能是主节点负载太大造成的
解决方案主要有两种:- 把主从节点的职责分离,设置三个储备主节点,node.master=true,node.data=false,从节点只存储数据,node.master=false,node.data=true
- 增加延迟时间:将储备主节点数最小设为n/2+1个
213. 详细描述一下Elasticsearch更新和删除文档的过程。
- 删除和更新也都是写操作,但是Elasticsearch中的文档是不可变的,因此不能被删除或者改动以展示其变更;
- 磁盘上的每个段都有一个相应的.del文件。当删除请求发送后,文档并没有真的被删除,而是在.del文件中被标记为删除。该文档依然能匹配查询,但是会在结果中被过滤掉。当段合并时,在.del文件中被标记为删除的文档将不会被写入新段。
- 在新的文档被创建时,Elasticsearch会为该文档指定一个版本号,当执行更新时,旧版本的文档在.del文件中被标记为删除,新版本的文档被索引到一个新段。旧版本的文档依然能匹配查询,但是会在结果中被过滤掉。
214. 在并发情况下,Elasticsearch如果保证读写一致?
可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用层来处理具体的冲突;
另外对于写操作,一致性级别支持quorum/one/all,默认为quorum,即只有当大多数分片可用时才允许写操作。但即使大多数可用,也可能存在因为网络等原因导致写入副本失败,这样该副本被认为故障,分片将会在一个不同的节点上重建。
对于读操作,可以设置replication为sync(默认),这使得操作在主分片和副本分片都完成后才会返回;如果设置replication为async时,也可以通过设置搜索请求参数_preference为primary来查询主分片,确保文档是最新版本。
215. 如何监控Elasticsearch集群状态?
Marvel 让你可以很简单的通过 Kibana 监控 Elasticsearch。你可以实时查看你的集群健康状态和性能,也可以分析过去的集群、索引和节点指标。
216. Elasticsearch中的倒排索引是什么?
倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。倒排索引是一种像数据结构一样的散列图,可将用户从单词导向文档或网页。它是搜索引擎的核心。其主要目标是快速搜索从数百万文件中查找数据。
217. ElasticSearch中的分片是什么?
在大多数环境中,每个节点都在单独的盒子或虚拟机上运行。
- 索引:在Elasticsearch中,索引是文档的集合。
- 分片:因为Elasticsearch是一个分布式搜索引擎,所以索引通常被分割成分布在多个节点上的被称为分片的元素。
218. ElasticSearch中的副本是什么?
一个索引被分解成碎片以便于分发和扩展。副本是分片的副本。一个节点是一个属于一个集群的ElasticSearch的运行实例。一个集群由一个或多个共享相同集群名称的节点组成。
219. ElasticSearch中的分析器是什么?
在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。 分析器由一个Tokenizer和零个或多个TokenFilter组成。编译器可以在一个或多个CharFilter之前。分析模块允许您在逻辑名称下注册分析器,然后可以在映射定义或某些API中引用它们。
Elasticsearch附带了许多可以随时使用的预建分析器。或者,您可以组合内置的字符过滤器,编译器和过滤器器来创建自定义分析器。
220. 什么是ElasticSearch中的编译器?
编译器用于将字符串分解为术语或标记流。一个简单的编译器可能会将字符串拆分为任何遇到空格或标点的地方。Elasticsearch有许多内置标记器,可用于构建自定义分析器。
221. Elasticsearch是如何实现高亮?
使用高亮碎片.先创建高亮字段碎片HighlightBuilder.Field对象.然后设置高亮字段Field进行标签设置(preTags和postTags),最后设置文本前后字节数,fragmentSize。
222. 如何实现搜索排名
当你创建了SearchQuery对象后,你可以对任意字段进行排序,里面的addSort方法,在给他一个Sort对象即可,如果在嵌套域查询中.可设置得分情况,在QueryBuilder中的nesterQuery中可设置得分情况。
223. 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。
224. Java有没有goto?
java中的保留字,现在没有在java中使用。
225. 说说&和&&的区别。
&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,例如,对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException如果将&&改为&,则会抛出NullPointerException异常。If(x33 & ++y>0) y会增长,If(x33 && ++y>0)不会增长
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如,0x31 & 0x0f的结果为0x01。
226. 在JAVA中如何跳出当前的多重嵌套循环?
在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环。例如,
ok:
for(int i=0;i<10;i++) {
for(int j=0;j<10;j++) {
System.out.println(“i=” + i + “,j=” + j);
if(j == 5) break ok;
}
}
另外,我个人通常并不使用标号这种方式,而是让外层的循环条件表达式的结果可以受到里层循环体代码的控制,例如,要在二维数组中查找到某个数字。
int arr[][] = {
{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i<arr.length && !found;i++) {
for(int j=0;j<arr[i].length;j++){
System.out.println(“i=” + i + “,j=” + j);
if(arr[i][j] == 5) {
found = true;
break;
}
}
}
227. switch语句能否作用在byte上,能否作用在long上,能否作用在String上?
在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。
228. short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。
对于short s1 = 1; s1 += 1;由于 += 是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
229. char型变量中能不能存贮一个中文汉字?为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
230. 用最有效率的方法算出2乘以8等於几?
2 << 3,因为将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,而位运算cpu直接支持的,效率最高,所以,2乘以8等於几的最效率的方法是2 << 3。
231. 请设计一个一百亿的计算器
首先要明白这道题目的考查点是什么,一是大家首先要对计算机原理的底层细节要清楚、要知道加减法的位运算原理和知道计算机中的算术运算会发生越界的情况,二是要具备一定的面向对象的设计思想。
首先,计算机中用固定数量的几个字节来存储的数值,所以计算机中能够表示的数值是有一定的范围的,为了便于讲解和理解,我们先以byte 类型的整数为例,它用1个字节进行存储,表示的最大数值范围为-128到+127。-1在内存中对应的二进制数据为11111111,如果两个-1相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,11111110,由于进位后超过了byte类型的存储空间,所以进位部分被舍弃,即最终的结果为11111110,也就是-2,这正好利用溢位的方式实现了负数的运算。-128在内存中对应的二进制数据为10000000,如果两个-128相加,不考虑Java运算时的类型提升,运算后会产生进位,二进制结果为1,00000000,由于进位后超过了byte类型的存储空间,所以进位部分被舍弃,即最终的结果为00000000,也就是0,这样的结果显然不是我们期望的,这说明计算机中的算术运算是会发生越界情况的,两个数值的运算结果不能超过计算机中的该类型的数值范围。由于Java中涉及表达式运算时的类型自动提升,我们无法用byte类型来做演示这种问题和现象的实验,大家可以用下面一个使用整数做实验的例子程序体验一下:
int a = Integer.MAX_VALUE;
int b = Integer.MAX_VALUE;
int sum = a + b;
System.out.println(“a=”+a+”,b=”+b+”,sum=”+sum);
先不考虑long类型,由于int的正数范围为2的31次方,表示的最大数值约等于210001000*1000,也就是20亿的大小,所以,要实现一个一百亿的计算器,我们得自己设计一个类可以用于表示很大的整数,并且提供了与另外一个整数进行加减乘除的功能,大概功能如下:
()这个类内部有两个成员变量,一个表示符号,另一个用字节数组表示数值的二进制数
()有一个构造方法,把一个包含有多位数值的字符串转换到内部的符号和字节数组中
()提供加减乘除的功能
public class BigInteger {
int sign;
byte[] val;
public Biginteger(String val) {
sign =;
val =;
}
public BigInteger add(BigInteger other) {
}
public BigInteger subtract(BigInteger other) {
}
public BigInteger multiply(BigInteger other) {
}
public BigInteger divide(BigInteger other) {
}
}
232. 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。例如,对于如下语句:
final StringBuffer a=new StringBuffer("immutable");
执行如下语句将报告编译期错误:
a=new StringBuffer("");
但是,执行如下语句则可以通过编译:
a.append(" broken!");
有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象:
public void method(final StringBuffer param){}
实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象:
param.append("a");
233. "=="和equals方法究竟有什么区别?
操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式ab将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用会