前言
最近有很多粉丝问我,有什么方法能够快速提升自己,通过阿里、腾讯、字节跳动、京东等互联网大厂的面试,我觉得短时间提升自己最快的手段就是背面试题,最近总结了Java常用的面试题,分享给大家,希望大家都能圆梦大厂,加油,我命由我不由天。
6. Java中引用数据类型有哪些,它们与基本数据类型有什么区别?
11. 能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?
17. 为什么有些java类要实现Serializable接口
18. 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
21. try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
27. 两个对象的 hashCode() 相同, 那么 equals() 也一定为 true吗?
34. ConcurrentModificationException异常出现的原因
35. HashMap和HashTable、ConcurrentHashMap区别?
1. Java 中操作字符串都有哪些类?它们之间有什么区别?
2. String、StringBuffer和StringBuilder区别(类似上一题)
4. String str="i"与 String str=new String("i")一样吗?
6. String s = new String("xyz");创建了几个StringObject?是否可以继承String类?
7. 下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
9. List、Map、Set三个接口,存取元素时,各有什么特点?
10. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用==还是equals()?它们有何区别?
13. ArrayList,Vector,LinkedList的存储性能和特性
18. LinkedHashMap和PriorityQueue的区别
19. WeakHashMap与HashMap的区别是什么?
36. 为何Collection不从Cloneable和Serializable接口继承?
39. Iterator和ListIterator的区别是什么?
40. Enumeration和Iterator接口的区别?
41. 为何没有像Iterator.add()这样的方法,向集合中添加元素?
42. 为何迭代器没有一个方法可以直接获取下一个元素,而不需要移动游标?
43. Iterater和ListIterator之间有什么区别?
47. 在迭代一个集合的时候,如何避免ConcurrentModificationException?
49. UnsupportedOperationException是什么?
51. hashCode()和equals()方法有何重要性?
57. Array和ArrayList有何区别?什么时候更适合用Array?
66. Comparable和Comparator接口是什么?
67. Comparable和Comparator接口有何区别?
69. 当一个集合被作为参数传递给一个函数时,如何才可以确保函数不能修改它?
70. 我们如何从给定集合那里创建一个synchronized的集合?
74. TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
3. 简述线程、程序、进程的基本概念。以及他们之间关系是什么?
8. 为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
12. 在多线程中,什么是上下文切换(context-switching)?
20. 什么是线程调度器(Thread Scheduler)和时间分片(Time Slicing)?
22. volatile 变量和 atomic 变量有什么不同?
26. 线程的sleep()方法和yield()方法有什么区别?
38. ThreadLocal原理,使用注意点,应用场景有哪些?
39. notify()和notifyAll()有什么区别?
40. 为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用
41. wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别
42. wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别
44. 什么是阻塞(Blocking)和非阻塞(Non-Blocking)?
49. 在Java中Executor、ExecutorService、Executors的区别?
55. 高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池?
57. Java中interrupted 和isInterruptedd方法的区别?
58. Java线程池中submit() 和 execute()方法有什么区别?
59. 说一说自己对于 synchronized 关键字的了解
60. 说说自己是怎么使用 synchronized 关键字,在项目中用到了吗synchronized关键字最主要的三种使用方式:
70. synchronized和ReentrantLock的区别
77. CyclicBarrier和CountDownLatch的区别
78. Hashtable的size()方法中明明只有一条语句"return count",为什么还要做同步?
1. 什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
4. Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?
6. 解释内存中的栈(stack)、堆(heap)和方法区(method area)的用法
17. 如果对象的引用被置为 null,垃圾收集器是否会立即释放对象占用的内存?
29. 串行(serial)收集器和吞吐量(throughput)收集器的区别
32. MinorGC,MajorGC、FullGC都什么时候发生?
38. System.gc() 和 Runtime.gc() 会做什么事情?
39. 垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
46. finalize() 方法什么时候被调用?析构函数 (finalization) 的目的是什么?
49. 假如生产环境CPU占用过高,请谈谈你的分析思路和定位。
22. 客户端不断进行请求链接会怎样?DDos(Distributed Denial of Service)攻击?
33. 浏览器中输入:“www.xxx.com” 之后都发生了什么?请详细阐述。
34. 什么是 HTTP 协议无状态协议?怎么解决Http协议无状态协议?
35. Session、Cookie 与 Application
3. MySQL中varchar与char的区别以及varchar(50)中的50代表的涵义
5. MySQL的binlog有有几种录入格式?分别有什么区别?**
7. 关心过业务系统里面的sql耗时吗?统计过慢查询吗?对慢查询都怎么优化过?**
8. 上面提到横向分表和纵向分表,可以分别举一个适合他们的例子吗?
13. 如果一个表有一列定义为TIMESTAMP,将发生什么?
15. MySQL 数据库作发布系统的存储,一天五万条以上的增量, 预计运维三年,怎么优化?
17. 简单描述 MySQL 中,索引,主键,唯一索引,联合索引的区别,对数据库的性能有什么影响(从读写两方面)
28. 如果要存储用户的密码散列,应该使用什么字段进行存储?
38. Hash索引和B+树所有有什么区别或者说优劣呢?**
40. 上面提到了B+树在满足聚簇索引和覆盖索引的时候不需要回表查询数据,什么是聚簇索引?
43. 联合索引是什么?为什么需要注意联合索引中的顺序?**
44. 创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因?
45. 那么在哪些情况下会发生针对该列创建了索引但是在查询的时候并没有使用呢?
51. 怎么解决这些问题呢?MySQL的事务隔离级别了解吗?
56. MySQL都有哪些锁呢?像上面那样子进行锁定岂不是有点阻碍并发效率了?
12. Redis 集群方案什么情况下会导致整个集群不可用?
13. MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中的数据都是热点数据?
24. Redis key 的过期时间和永久有效分别怎么设置?
30. 使用过 Redis 做异步队列么,你是怎么用的?有什么缺点?**
31. 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
34. redis 和 memcached 什么区别?为什么高并发下有时单线程的 redis 比多线程的memcached 效率要高?**
35. 使用 redis 如何设计分布式锁?说一下实现思路?使用 zk 可以吗?如何实现?这两种有什么区别?
36. 知道 redis 的持久化吗?底层如何实现的?有什么优点缺点?
37. redis 持久化机制(怎么保证 redis 挂掉之后再重启数据可以进行恢复)
39 在选择缓存时,什么时候选择 redis,什么时候选择 memcached?
47. 请用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次。具体登录函数或功能用空函数即可,不用详细写出。
7. 什么是NoSQL数据库?NoSQL与RDBMS直接有什么区别?为什么要使用和不使用NoSQL数据库?说一说NoSQL数据库的几个优点?
10. 你怎么比较MongoDB、CouchDB及CouchBase?
11. MongoDB成为最好NoSQL数据库的原因是什么?
12. journal回放在条目(entry)不完整时(比如恰巧有一个中途故障了)会遇到问题吗?
23. 必须调用getLastError来确保写操作生效了么?
24. 我应该启动一个集群分片(sharded)还是一个非集群分片的 MongoDB 环境?
25. 分片(sharding)和复制(replication)是怎样工作的?
27. 当我试图更新一个正在被迁移的块(chunk)上的文档时会发生什么?
28. 如果在一个分片(shard)停止或者很慢的时候,我发起一个查询会怎样?
31. 如果块移动操作(moveChunk)失败了,我需要手动清除部分转移的文档吗?
32. 如果我在使用复制技术(replication),可以一部分使用日志(journaling)而其他部分则不使用吗?
33. MongoDB在A:{B,C}上建立索引,查询A:{B,C}和A:{C,B}都会使用索引吗?
34. 如果一个分片(Shard)停止或很慢的时候,发起一个查询会怎样?
35. MongoDB支持存储过程吗?如果支持的话,怎么用?
36. 如何理解MongoDB中的GridFS机制,MongoDB为何使用GridFS来存储文件?
37. MongoDB支持存储过程吗?如果支持的话,怎么用?
38. 如何理解MongoDB中的GridFS机制,MongoDB为何使用GridFS来存储文件?
40. MongoDB在A:{B,C}上建立索引,查询A:{B,C}和A:{C,B}都会使用索引吗?
47. 分片(sharding)和复制(replication)是怎样工作的?
62. 如何查看使用MongoDB的连接Sharding - MongoDB Manual21.如何查看使用MongoDB的连接
65. 在MongoDB中如何除去一个数据库Collection Methods24.在MongoDB中如何除去一个数据库
72. 为什么要在MongoDB中用"Regular Expression"数据类型
73. 为什么在MongoDB中使用"Object ID"数据类型
78. 如何使用"AND"或"OR"条件循环查询集合中的文档
10. 在 Spring 中,有几种配置 Bean 的方式?
12. BeanFactory和ApplicationContext有什么区别?
16. Spring Bean 有哪些作用域,它们之间有什么区别?
17. Springmvc controller方法中为什么不能定义局部变量?
23. 请解释一下,Spring 框架有哪些自动装配模式,它们之间有何区别?
24. Springmvc 中DispatcherServlet初始化过程。
25. SpringMVC执行流程和原理 SpringMVC流程:
29. @Component, @Controller, @Repository, @Service 有何区别?
37. SpringMVC中的拦截器和Servlet中的filter有什么区别?
41. Spring 中的 IoC 的实现原理就是工厂模式加反射机制。
45. 在Spring AOP 中,关注点和横切关注的区别是什么?
47. Spring事务的实现方式和实现原理:讲讲Spring事务的传播属性。
52. Spring怎么配置事务(具体说出一些关键的xml 元素)。
55. 说说 BeanFactory 和 ApplicationContext 的区别? 什么是延迟实例化,它的优缺点是什么?
56. BeanFactory – BeanFactory 实现举例
6. Mybatis 比 IBatis 比较大的几个改进是什么?
8. 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
10. JDBC编程有哪些不足之处,MyBatis是如何解决的?
18. 当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
20. Mybatis都有哪些Executor执行器?它们之间的区别是什么?
21. Mybatis中如何指定使用哪一种Executor执行器?
22. 通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
23. Mybatis是如何进行分页的?分页插件的原理是什么?
24. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
27. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
28. Mybatis动态sql有什么用?执行原理?有哪些动态sql?
29. Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?
30. Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
31. 为什么说Mybatis是半自动ORM映射工具?它与全自动的区别在哪里?
33. MyBatis 里面的动态 Sql 是怎么设定的?用什么语法?
34. Mybatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别?
35. MyBatis实现一对一有几种方式?具体怎么操作的?
37. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
42. 使用MyBatis的mapper接口调用时有哪些要求?
44. Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能**否定义在 A 标签的后面,还是说必须定义在 A 标签的前面?
45. 简述Mybatis的插件运行原理,以及如何编写一个插件。
46. Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
47. 简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?
4. 怎么理解 Spring Boot 中 “约定优于配置“
5. 如何在自定义端口上运行 Spring Boot应用程序?
12. Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个
13. 如何重新加载Spring Boot上的更改,而无需重新启动服务器?
14. 你如何理解 Spring Boot 中的 Starters?
15. spring-boot-starter-parent 有什么用 ?
18. Spring Boot 的核心配置文件有哪几个?它们的区别是什么?
19. Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
20. 创建一个 Spring Boot Project 的最简单的方法是什么?
21. Spring Initializr 是创建 Spring Boot Projects 的唯一方法吗?
22. 如何集成 Spring Boot 和 ActiveMQ?
23. 什么是 Swagger?你用 Spring Boot 实现了它吗?
25. Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?
28. Spring Boot 还提供了其它的哪些 Starter Project Options?
29. 为什么我们需要 spring-boot-maven-plugin?
32. Spring Boot、Spring MVC 和 Spring 有什么区别?
40. 什么是嵌入式服务器?我们为什么要使用嵌入式服务器呢?
41. 当 Spring Boot 应用程序作为 Java 应用程序运行时,后台会发生什么?
42. RequestMapping 和 GetMapping 的不同之处在哪里?
43. 为什么我们不建议在实际的应用程序中使用 Spring Data Rest?
2.2. @Component, @Repository, @Service, @Controller
4.1. @PathVariable 和 @RequestParam
5.2. @ConfigurationProperties(常用)
6.3. 验证请求参数(Path Variables 和 Request Parameters)
11. Eureka和zookeeper都可以提供服务注册与发现的功能,请说说两个的区别?
14. SpringBoot 和 SpringCloud 之间关系?
15. SpringCloud 和 Dubbo 有哪些区别?
23. 什么是 Netflix Feign?它的优点是什么?
25. 服务注册和发现是什么意思?Spring Cloud如何实现?
29. 什么是 Spring Cloud Bus?我们需要它吗?
3. Dubbo 和 Spring Cloud 有什么区别?
12. 在 Provider 上可以配置的 Consumer 端的属性有哪些?
14. Dubbo推荐使用什么序列化框架,你知道的还有哪些?
15. Dubbo默认使用的是什么通信框架,还有别的选择吗?
18. 注册了多个同一样的服务,如果测试指定的某一个服务呢?
20. Dubbo 支持哪些协议,每种协议的应用场景,优缺点?
8. 请解释Nginx服务器上的Master和Worker进程分别是什么?
15. Nginx配置文件nginx.conf有哪些属性模块?
12. 集群中有 3 台服务器,其中一个节点宕机,这个时候 Zookeeper 还可以使用吗?
16. Zookeeper Watcher 机制 -- 数据变更通知
21. zookeeper 负载均衡和 nginx 负载均衡区别
25. Zookeeper 对节点的 watch 监听通知是永久的吗?为什么不是永久的?
31. 交换器无法根据自身类型和路由键找到符合条件队列时,有哪些处理?
3. Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么
6. Kafka中的 zookeeper 起到什么作用,可以不用zookeeper么**
2. 安装 Elasticsearch 需要依赖什么组件吗?
4. ElasticSearch中的集群、节点、索引、文档、类型是什么?
11. 解释一下 Elasticsearch 集群中的 Type 的概念 ?
14. Elasticsearch Analyzer 中的字符过滤器如何利用?
15. REST API在 Elasticsearch 方面有哪些优势?
16. Elasticsearch 中常用的 cat命令有哪些?
17. 你能否列出与 Elasticsearch 有关的主要可用字段数据类型?
18. Elasticsearch了解多少,说说你们公司es的集群架构,索引数据大小,分片有多少,以及一些调优手段 。
19. 解释一下 Elasticsearch集群中的 索引的概念 ?
20. Elasticsearch 索引数据多了怎么办,如何调优,部署
21. 我们可以在 Elasticsearch 中执行搜索的各种可能方式有哪些?
22. 在 Elasticsearch 中删除索引的语法是什么?
23. 在 Elasticsearch 中列出集群的所有索引的语法是什么?
29. 请解释在 Elasticsearch 集群中添加或创建索引的过程?
30. 详细描述一下Elasticsearch索引文档的过程。
31. 详细描述一下Elasticsearch更新和删除文档的过程
33. Elasticsearch对于大数据量(上亿量级)的聚合如何实现?
34. 你可以列出 Elasticsearch 各种类型的分析器吗?
36. Master 节点和 候选 Master节点有什么区别?
37. Elasticsearch中的属性 enabled, index 和 store 的功能是什么?
38. Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
46. 说说你们公司ES的集群架构,索引数据大小,分片有多少,以及一些调优手段?
47. 在并发情况下,Elasticsearch如果保证读写一致?
Java相关
基础&进阶篇
1.什么是Java
Java是一门面向对象的高级编程语言,不仅吸收了C++语言的各种优点,比如继承了C++语言面向对象的技术核心。还摒弃了C++里难以理解的多继承、指针等概念,,同时也增加了垃圾回收机制,释放掉不被使用的内存空间,解决了管理内存空间的烦恼。
因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
2. Java的特点有哪些
Java 语言是一种分布式的面向对象语言,具有面向对象、平台无关性、简单性、解释执行、多线程、安
全性等很多特点,下面针对这些特点进行逐一介绍。
1. 面向对象
Java 是一种面向对象的语言,它对对象中的类、对象、继承、封装、多态、接口、包等均有很好的支持。为了简单起见,Java 只支持类之间的单继承,但是可以使用接口来实现多继承。使用 Java 语言开发程序,需要采用面向对象的思想设计程序和编写代码。
2. 平台无关性
平台无关性的具体表现在于,Java 是“一次编写,到处运行(Write Once,Run any Where)”的语言,因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。在引入虚拟机之后,Java 语言在不同的平台上运行不需要重新编译。
Java 语言使用 Java 虚拟机机制屏蔽了具体平台的相关信息,使得 Java 语言编译的程序只需生成虚拟机上的目标代码,就可以在多种平台上不加修改地运行。
3. 简单性
Java 语言的语法与 C 语言和 C++ 语言很相近,使得很多程序员学起来很容易。对 Java 来说,它舍弃了很多 C++ 中难以理解的特性,如操作符的重载和多继承等,而且 Java 语言不使用指针,加入了垃圾回收机制,解决了程序员需要管理内存的问题,使编程变得更加简单。
4. 解释执行
Java 程序在 Java 平台运行时会被编译成字节码文件,然后可以在有 Java 环境的操作系统上运行。在运行文件时,Java 的解释器对这些字节码进行解释执行,执行过程中需要加入的类在连接阶段被载入到运行环境中。
5. 多线程
Java 语言是多线程的,这也是 Java 语言的一大特性,它必须由 Thread 类和它的子类来创建。Java 支持多个线程同时执行,并提供多线程之间的同步机制。任何一个线程都有自己的 run() 方法,要执行的方法就写在 run() 方法体内。
6. 分布式
Java 语言支持 Internet 应用的开发,在 Java 的基本应用编程接口中就有一个网络应用编程接口,它提供了网络应用编程的类库,包括 URL、URLConnection、Socket 等。Java 的 RIM 机制也是开发分布式应用的重要手段。
7. 健壮性
Java 的强类型机制、异常处理、垃圾回收机制等都是 Java 健壮性的重要保证。对指针的丢弃是 Java 的一大进步。另外,Java 的异常机制也是健壮性的一大体现。
8. 高性能
Java 的高性能主要是相对其他高级脚本语言来说的,随着 JIT(Just in Time)的发展,Java 的运行速度也越来越高。
9. 安全性
Java 通常被用在网络环境中,为此,Java 提供了一个安全机制以防止恶意代码的攻击。除了 Java 语言具有许多的安全特性以外,Java 还对通过网络下载的类增加一个安全防范机制,分配不同的名字空间以防替代本地的同名类,并包含安全管理机制。
Java 语言的众多特性使其在众多的编程语言中占有较大的市场份额,Java 语言对对象的支持和强大的API 使得编程工作变得更加容易和快捷,大大降低了程序的开发成本。Java 的“一次编写,到处执行”正是它吸引众多商家和编程人员的一大优势。
3. JDK和JRE和JVM的区别
1. JDK
JDK(Java SE Development Kit),Java标准的开发包,提供了编译、运行Java程序所需要的各种工具和资源,包括了Java编译器、Java运行时环境、以及常用的Java类库等。
2. JRE
JRE(Java Runtime Environment),Java运行时环境,用于解释执行Java的字节码文件。普通用户只需要安装JRE来运行Java程序即可,而作为一名程序员必须安装JDK,来编译、调试程序。
3. JVM
JVM(Java Virtual Mechinal),Java虚拟机,是JRE的一部分。它是整个Java实现跨平台的核心,负责解释执行字节码文件,是可运行Java字节码文件的虚拟计算机。所有平台上的JVM向编译器提供相同的接口,而编译器只需要面向虚拟机,生成虚拟机能识别的代码,然后由虚拟机来解释执行。当使用Java编译器编译Java程序时,生成的是与平台无关的字节码,这些字节码只面向JVM。也就是说
JVM是运行Java字节码的虚拟机。
不同平台的JVM是不同的,但是他们都提供了相同的接口。JVM是Java程序跨平台的关键部分,只要为不同平台实现了相同的虚拟机,编译后的Java字节码就可以在该平台上运行。
为什么要采用字节码:
在 Java 中,JVM 可以理解的代码就叫做 字节码 (即Java源代码经过虚拟机编译器编译后扩展名为.class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式, 在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。 所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无 须重新编译便可在多种不同操作系统的计算机上运行。
什么是跨平台:
所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。
实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟 机,该系统就可以运行java程序。
Java 程序从源代码到运行需要三步:
4. 总结
1. JDK 用于开发,JRE 用于运行java程序 ;如果只是运行Java程序,可以只安装JRE,无序安装JDK。
2. JDk包含JRE,JDK 和 JRE 中都包含 JVM。
3. JVM 是 Java 编程语言的核心并且具有平台独立性。
4. Oracle JDK 和 OpenJDK 的对比
- Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
- OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全 开源的;
- Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
- 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
- Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来 获取最新版本;
- Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。
5. Java有哪些数据类型
Java中有 8 种基本数据类型,分别为:
- 6 种数字类型 (四个整数形,两个浮点型):byte、short、int、long、float、double
- 1 种字符类型:char
- 1 种布尔型:boolean。
byte:
- byte 数据类型是8位、有符号的,以二进制补码表示的整数;
- 最小值是 -128(-2^7);
- 最大值是 127(2^7-1);
- 默认值是 0;
- byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四 分之一;
- 例子:byte a = 100,byte b = -50。
short:
- short 数据类型是 16 位、有符号的以二进制补码表示的整数
- 最小值是 -32768(-2^15);
- 最大值是 32767(2^15 - 1);
- Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
- 默认值是 0;
- 例子:short s = 1000,short r = -20000。
int:
- int 数据类型是32位、有符号的以二进制补码表示的整数;
- 最小值是 -2,147,483,648(-2^31);
- 最大值是 2,147,483,647(2^31 - 1);
- 一般地整型变量默认为 int 类型;
- 默认值是 0 ;
- 例子:int a = 100000, int b = -200000。
long:
- 注意:Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析
- long 数据类型是 64 位、有符号的以二进制补码表示的整数;
- 最小值是 -9,223,372,036,854,775,808(-2^63);
- 最大值是 9,223,372,036,854,775,807(2^63 -1);
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是 0L;
- 例子: long a = 100000L,Long b = -200000L。 "L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。
float:
- float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
- float 在储存大型浮点数组的时候可节省内存空间;
- 默认值是 0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 例子:float f1 = 234.5f。
double:
- double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
- 浮点数的默认类型为double类型;
- double类型同样不能表示精确的值,如货币;
- 默认值是 0.0d;
- 例子:double d1 = 123.4。
char:
- char类型是一个单一的 16 位 Unicode 字符;
- 最小值是 \u0000(即为 0);
- 最大值是 \uffff(即为 65535);
- char 数据类型可以储存任何字符;
- 例子:char letter = 'A';(单引号)
boolean:
- boolean数据类型表示一位的信息;
- 只有两个取值:true 和 false;
- 这种类型只作为一种标志来记录 true/false 情况;
- 默认值是 false;
- 例子:boolean one = true。
这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、 Character、Boolean
6. Java中引用数据类型有哪些,它们与基本数据类型有什么区别?
引用数据类型分3种:类,接口,数组;
简单来说,只要不是基本数据类型.都是引用数据类型。 那他们有什么不同呢?
1、从概念方面来说
1,基本数据类型:变量名指向具体的数值
2,引用数据类型:变量名不是指向具体的数值,而是指向存数据的内存地址,.也及时hash值
2、从内存的构建方面来说(内存中,有堆内存和栈内存两者)
1,基本数据类型:被创建时,在栈内存中会被划分出一定的内存,并将数值存储在该内存中.
2,引用数据类型:被创建时,首先会在栈内存中分配一块空间,然后在堆内存中也会分配一块具体的空间用来存储数据的具体信息,即hash值,然后由栈中引用指向堆中的对象地址.
举个例子
//基本数据类型作为方法参数被调用
public class Main{
public static void main(String[] args){
//基本数据类型
int i = 1;
int j = 1;
double d = 1.2;
//引用数据类型
String str = "Hello";
String str1= "Hello";
}
}
由上图可知,基本数据类型中会存在两个相同的1,而引用型类型就不会存在相同的数据。
假如"hello"的引用地址是xxxxx1,声明str变量并其赋值"hello"实际上就是让str变量引用了"hello"的内存地址,这个内存地址就存储在堆内存中,是不会改变的,当再次声明变量str1也是赋值为"hello"时,此时就会在堆内存中查询是否有"hello"这个地址,如果堆内存中已经存在这个地址了,就不会再次创建了,而是让str1变量也指向xxxxx1这个地址,如果没有的话,就会重新创建一个地址给str1变量。
7. 从使用方面来说
1,基本数据类型:判断数据是否相等,用==和!=判断。
2,引用数据类型:判断数据是否相等,用equals()方法,==和!=是比较数值的。而equals()方法是比较内存地址的。
补充:数据类型选择的原则
- 如果要表示整数就使用int,表示小数就使用double;
- 如果要描述日期时间数字或者表示文件(或内存)大小用long;
- 如果要实现内容传递或者编码转换使用byte;
- 如果要实现逻辑的控制,可以使用booleam;
- 如果要使用中文,使用char避免中文乱码;
- 如果按照保存范围:byte < int < long < double
8. Java中的自动装箱与拆箱
什么是自动装箱拆箱?
从下面的代码中就可以看到装箱和拆箱的过程
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
装箱就是自动将基本数据类型转换为包装器类型;拆箱就是自动将包装器类型转换为基本数据类型。
在Java SE5之前,自动装箱要这样写:Integer i = new` `Integer( 10``);
对于Java的自动装箱和拆箱,我们看看源码编译后的class文件,其实装箱调用包装类的valueOf方法,拆箱调用的是Integer.Value方法,下面就是变编译后的代码:
......
Java并发编程
1. 多线程有什么用?
一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法:
(1)、发挥多核CPU的优势
随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。
(2)、防止阻塞
从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。
(3)、便于建模
这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。
2. 多线程和单线程的区别和联系?
1、在单核 CPU 中,将 CPU 分为很小的时间片,在每一时刻只能有一个线程在执行,是一种微观上轮流占用 CPU 的机制。
2、多线程会存在线程上下文切换,会导致程序执行速度变慢,即采用一个拥有两个线程的进程执行所需要的时间比一个线程的进程执行两次所需要的时间要多一些。
结论:即采用多线程不会提高程序的执行速度,反而会降低速度,但是对于用户来说,可以减少用户的响应时间。
3. 简述线程、程序、进程的基本概念。以及他们之间关系是什么?
线程
与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
程序
是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。
进程
是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如 CPU 时间,内存空间,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。从另一角度来说,进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。
4. 线程的创建方式
方法一:继承Thread类,作为线程对象存在(继承Thread对象)
public class CreatThreadDemo1 extends Thread{
/**
* 构造方法: 继承父类方法的Thread(String name);方法
* @param name
*/
public CreatThreadDemo1(String name){
super(name);
}
@Override
public void run() {
while (!interrupted()){
System.out.println(getName()+"线程执行了...");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
CreatThreadDemo1 d1 = new CreatThreadDemo1("first");
CreatThreadDemo1 d2 = new CreatThreadDemo1("second");
d1.start();
d2.start();
d1.interrupt(); //中断第一个线程
}
}
常规方法,不多做介绍了,interrupted方法,是来判断该线程是否被中断。(终止线程不允许用stop方法,该方法不会施放占用的资源。所以我们在设计程序的时候,要按照中断线程的思维去设计,就像上面的代码一样)。
让线程等待的方法
- Thread.sleep(200); //线程休息2ms
- Object.wait(); //让线程进入等待,直到调用Object的notify或者notifyAll时,线程停止休眠
方法二:实现runnable接口,作为线程任务存在
public class CreatThreadDemo2 implements Runnable {
@Override
public void run() {
while (true){
System.out.println("线程执行了...");
}
}
public static void main(String[] args) {
//将线程任务传给线程对象
Thread thread = new Thread(new CreatThreadDemo2());
//启动线程
thread.start();
}
}
Runnable 只是来修饰线程所执行的任务,它不是一个线程对象。想要启动Runnable对象,必须将它放到一个线程对象里。
方法三:匿名内部类创建线程对象
public class CreatThreadDemo3 extends Thread{
public static void main(String[] args) {
//创建无参线程对象
new Thread(){
@Override
public void run() {
System.out.println("线程执行了...");
}
}.start();
//创建带线程任务的线程对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程执行了...");
}
}).start();
//创建带线程任务并且重写run方法的线程对象
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("runnable run 线程执行了...");
}
}){
@Override
public void run() {
System.out.println("override run 线程执行了...");
}
}.start();
}
}
创建带线程任务并且重写run方法的线程对象中,为什么只运行了Thread的run方法。我们看看Thread类的源码,
我们可以看到Thread实现了Runnable接口,而Runnable接口里有一个run方法。
所以,我们最终调用的重写的方法应该是Thread类的run方法。而不是Runnable接口的run方法。
方法四:创建带返回值的线程
public class CreatThreadDemo4 implements Callable {
public static void main(String[] args) throws ExecutionException,InterruptedException {
CreatThreadDemo4 demo4 = new CreatThreadDemo4();
FutureTask<Integer> task = new FutureTask<Integer>(demo4); //FutureTask最终实现的是runnable接口
Thread thread = new Thread(task);
thread.start();
System.out.println("我可以在这里做点别的业务逻辑...因为FutureTask是提前完成任务");
//拿出线程执行的返回值
Integer result = task.get();
System.out.println("线程中运算的结果为:"+result);
}
//重写Callable接口的call方法
@Override
public Object call() throws Exception {
int result = 1;
System.out.println("业务逻辑计算中...");
Thread.sleep(3000);
return result;
}
}
Callable接口介绍:
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
返回指定泛型的call方法。然后调用FutureTask对象的get方法得道call方法的返回值。
方法五:定时器Timer
public class CreatThreadDemo5 {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("定时器线程执行了...");
}
},0,1000); //延迟0,周期1s
}
}
方法六:线程池创建线程
public class CreatThreadDemo6 {
public static void main(String[] args) {
//创建一个具有10个线程的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(10);
long threadpoolUseTime = System.currentTimeMillis();
for (int i = 0;i<10;i++){
threadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程执行了...");
}
});
}
long threadpoolUseTime1 = System.currentTimeMillis();
System.out.println("多线程用时"+(threadpoolUseTime1-threadpoolUseTime));
//销毁线程池
threadPool.shutdown();
threadpoolUseTime = System.currentTimeMillis();
}
}
方法七:利用java8新特性 stream 实现并发
5. 线程有哪些基本状态?
Java 线程在运行的生命周期中的指定时刻只可能处于下面6种不同状态的其中一个状态(图源《Java 并发编程艺术》
线程在生命周期中并不是固定处于某一个状态而是随着代码的执行在不同状态之间切换。Java 线程状态变迁如下图所示(图源《Java 并发编程艺术》4.1.4节):
操作系统隐藏 Java虚拟机(JVM)中的 RUNNABLE 和 RUNNING 状态,它只能看到RUNNABLE 状态(图源:HowToDoInJava:Java Thread Life Cycle and Thread States),所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。
操作系统隐藏 Java虚拟机(JVM)中的 RUNNABLE 和 RUNNING 状态,它只能看到RUNNABLE状态(图源:HowToDoInJava:),所以 Java 系统一般将这两个状态统称为 RUNNABLE(运行中) 状态 。
当线程执行 wait() 方法之后,线程进入 WAITING(等待)状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 TIME_WAITING(超时等待) 状态相当于在等待状态的基础上增加了超时限制,比如通过 sleep(long millis) 方法或 wait(long millis) 方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 BLOCKED(阻塞) 状态。线程在执行 Runnable的 run() 方法之后将会进入到 TERMINATED(终止) 状态。
6. 如何停止一个正在运行的线程
1、使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2、使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。
3、使用interrupt方法中断线程。
class MyThread extends Thread {
volatile boolean stop = false;
public void run() {
while (!stop) {
System.out.println(getName() + " is running");
try {
sleep(1000);
} catch (InterruptedException e) {
System.out.println("week up from blcok...");
stop = true; // 在异常处理代码中修改共享变量的状态
}
}
System.out.println(getName() + " is exiting...");
}
}
class InterruptThreadDemo3 {
public static void main(String[] args) throws InterruptedException {
MyThread m1 = new MyThread();
System.out.println("Starting thread...");
m1.start();
Thread.sleep(3000);
System.out.println("Interrupt thread...: " + m1.getName());
m1.stop = true; // 设置共享变量为true
m1.interrupt(); // 阻塞时退出阻塞状态
Thread.sleep(3000); // 主线程休眠3秒以便观察线程m1的中断情况
System.out.println("Stopping application...");
}
}
因内容较多只展示部分内容,完整面试题以备好:
另还有: