Java中的原始数据类型都有哪些,它们的大小及对应的封装类是什么? byte——1 byte——Byte算法
short——2 bytes——Short编程
int——4 bytes——Integer设计模式
long——8 bytes——Long数组
float——4 bytes——Float缓存
double——8 bytes——Double安全
char——2 bytes——Character数据结构
boolean——————Boolean多线程
boolean数据类型非true即false。架构
这个数据类型表示1 bit,可是它的大小并无精肯定义。并发
《Java虚拟机规范》中如是说:“虽然定义了boolean这种数据类型,可是只对它提供了很是有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指令,Java语言表达式所操做的boolean值,在编译以后都使用Java虚拟机中的int数据类型来代替,而boolean数组将会被编码成Java虚拟机的byte数组,每一个元素boolean元素占8位”。这样咱们能够得出boolean类型单独使用是4个字节,在数组中又是1个字节。
那虚拟机为何要用int来代替boolean呢?为何不用byte或short,这样不是更节省内存空间吗?
实际上,使用int的缘由是,对于当下32位的CPU来讲,一次进行32位的数据交换更加高效。
综上,咱们能够知道:官方文档对boolean类型没有给出精确的定义,《Java虚拟机规范》给出了“单独时使用4个字节,boolean数组时1个字节”的定义,具体还要看虚拟机实现是否按照规范来,因此1个字节、4个字节都是有可能的。这实际上是一种时空权衡。 boolean类型的封装类是Boolean。
你们能够点击加入群:【Java高级架构进阶群】:854180697
里面有Java高级大牛直播讲解知识点 走的就是高端路线
(若是你想跳槽换工做 可是技术又不够 或者工做上遇到了瓶颈
我这里有一个JAVA的免费直播课程
讲的是高端的知识点基础很差的误入哟
只要你有1-5年的开发经验能够加群找我要课堂连接
注意:是免费的 没有开发经验误入哦)
谈一谈”==“与”equals()"的区别。 《Think in Java》中说:“关系操做符生成的是一个boolean结果,它们计算的是操做数的值之间的关系”。 "=="判断的是两个对象的内存地址是否同样,适用于原始数据类型和枚举类型(它们的变量存储的是值自己,而引用类型变量存储的是引用);equals是Object类的方法,Object对它的实现是比较内存地址,咱们能够重写这个方法来自定义“相等”这个概念。好比类库中的String、Date等类就对这个方法进行了重写。 综上,对于枚举类型和原始数据类型的相等性比较,应该使用"==";对于引用类型的相等性比较,应该使用equals方法。
Java中的四种引用及其应用场景是什么?
强引用: 一般咱们使用new操做符建立一个对象时所返回的引用即为强引用
软引用: 若一个对象只能经过软引用到达,那么这个对象在内存不足时会被回收,可用于图片缓存中,内存不足时系统会自动回收再也不使用的Bitmap
弱引用: 若一个对象只能经过弱引用到达,那么它就会被回收(即便内存充足),一样可用于图片缓存中,这时候只要Bitmap再也不使用就会被回收
虚引用: 虚引用是Java中最“弱”的引用,经过它甚至没法获取被引用的对象,它存在的惟一做用就是当它指向的对象回收时,它自己会被加入到引用队列中,这样咱们能够知道它指向的对象什么时候被销毁。
object中定义了哪些方法? clone()
equals()
hashCode()
toString()
notify()
notifyAll()
wait()
finalize()
getClass()
hashCode的做用是什么? 请参考散列表的基本原理与实现
ArrayList, LinkedList, Vector的区别是什么? ArrayList:内部采用数组存储元素,支持高效随机访问,支持动态调整大小
LinkedList:内部采用链表来存储元素,支持快速插入/删除元素,但不支持高效地随机访问
Vector: 能够看做线程安全版的ArrayList
String, StringBuilder, StringBuffer的区别是什么? String: 不可变的字符序列,若要向其中添加新字符须要建立一个新的String对象
StringBuilder: 可变字符序列,支持向其中添加新字符(无需建立新对象)
StringBuffer: 能够看做线程安全版的StringBuilder
Map, Set, List, Queue、Stack的特色及用法。 Map:Java中存储键值对的数据类型都实现了这个接口,表示“映射表”。支持的两个核心操做是get(Object key)以及put(K key, V value),分别用来获取键对应的值以及向映射表中插入键值对。
Set:实现了这个接口的集合类型中不容许存在重复的元素,表明数学意义上的“集合”。它所支持的核心操做有add(E e), remove(Object o), contains(Object o),分别用于添加元素,删除元素以及判断给定元素是否存在于集中。
List: Java中集合框架中的列表类型都实现了这个接口,表示一种有序序列。支持get(int index), add(E e)等操做。
Queue:Java集合框架中的队列接口,表明了“先进先出”队列。支持add(E element),remove()等操做。
Stack:Java集合框架中表示堆栈的数据类型,堆栈是一种“后进先出”的数据结构。支持push(E item), pop()等操做。
更详细的说明请参考官方文档,对相关数据结构不太熟悉的同窗能够参考《算法导论》或其余相关书籍。
HashMap和HashTable的区别 HashTable是线程安全的,而HashMap不是
HashMap中容许存在null键和null值,而HashTable中不容许
HashMap的实现原理 简单的说,HashMap的底层实现是“基于拉链法的散列表”。
详细分析请参考 Map源码解析之HashMap源码分析
ConcurrentHashMap的实现原理 ConcurrentHashMap是支持并发读写的HashMap,它的特色是读取数据时无需加锁,写数据时能够保证加锁粒度尽量的小。因为其内部采用“分段存储”,只需对要进行写操做的数据所在的“段”进行加锁。关于ConcurrentHashMap底层实现的详细分析请参考 Java并发编程:并发容器之ConcurrentHashMap
TreeMap, LinkedHashMap, HashMap的区别是什么? HashMap的底层实现是散列表,所以它内部存储的元素是无序的;
TreeMap的底层实现是红黑树,因此它内部的元素的有序的。排序的依据是天然序或者是建立TreeMap时所提供的比较器(Comparator)对象。
LinkedHashMap能够看做可以记住插入元素的顺序的HashMap。
Collection与Collections的区别是什么? Collection是Java集合框架中的基本接口;
Collections是Java集合框架提供的一个工具类,其中包含了大量用于操做或返回集合的静态方法。
对于“try-catch-finally”,若try语句块中包含“return”语句,finally语句块会执行吗?
会执行。只有两种状况finally块中的语句不会被执行:
调用了System.exit()方法;
JVM“崩溃”了。
Java中的异常层次结构
Java中的异常层次结构以下图所示:
咱们能够看到Throwable类是异常层级中的基类。
Error类表示内部错误,这类错误使咱们没法控制的;Exception表示异常,RuntimeException及其子类属于未检查异常,这类异常包括ArrayIndexOutOfBoundsException、NullPointerException等,咱们应该经过条件判断等方式语句避免未检查异常的发生。IOException及其子类属于已检查异常,编译器会检查咱们是否为全部可能抛出的已检查异常提供了异常处理器,若没有则会报错。对于未检查异常,咱们无需捕获(固然Java也容许咱们捕获,但咱们应该作的事避免未检查异常的发生)。
Java面向对象的三个特征与含义 三大特征:封装、继承、多态。
Override, Overload的含义与区别 Override表示“重写”,是子类对父类中同一方法的从新定义
Overload表示“重载”,也就是定义一个与已定义方法名称相同但签名不一样的新方法
接口与抽象类的区别 接口是一种约定,实现接口的类要遵循这个约定;
抽象类本质上是一个类,使用抽象类的代价要比接口大。
接口与抽象类的对好比下: 抽象类中能够包含属性,方法(包含抽象方法与有着具体实现的方法),常量;接口只能包含常量和方法声明。
抽象类中的方法和成员变量能够定义可见性(好比 public、private等);而接口中的方法只能为public(缺省为public)。
一个子类只能有一个父类(具体类或抽象类);而一个接口能够继承一个多个接口,一个类也能够实现多个接口。
子类中实现父类中的抽象方法时,可见性能够大于等于父类中的;而接口实现类中的接口 方法的可见性只能与接口中相同(public)。
静态内部类与非静态内部类的区别 静态内部类不会持有外围类的引用,而非静态内部类会隐式持有外围类的一个引用。
Java中多态的实现原理 所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。详细介绍请戳 Java动态绑定的内部实现机制
简述Java中建立新线程的两种方法
继承Thread类(假设子类为MyThread),并重写run()方法,而后new一个MyThread对象并对其调用start()便可启动新线程。
实现Runnable接口(假设实现类为MyRunnable),然后将MyRunnable对象做为参数传入Thread构造器,在获得的Thread对象上调用start()方法便可。
简述Java中进行线程同步的方法 volatile: Java Memory Model保证了对同一个volatile变量的写happens before对它的读;
synchronized:能够来对一个代码块或是对一个方法上锁,被“锁住”的地方称为临界区,进入临界区的线程会获取对象的monitor,这样其余尝试进入临界区的线程会因没法获取monitor而被阻塞。因为等待另外一个线程释放monitor而被阻塞的线程没法被中断。
ReentrantLock: 尝试获取锁的线程能够被中断并能够设置超时参数。
简述Java中具备哪几种粒度的锁
Java中能够对类、对象、方法或是代码块上锁。
给出“生产者-消费者”问题的一种解决方案
使用阻塞队列:
public class BlockingQueueTest { private int size = 20; private ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue<>(size); public static void main(String[] args) { BlockingQueueTest test = new BlockingQueueTest(); Producer producer = test.new Producer(); Consumer consumer = test.new Consumer(); producer.start(); consumer.start(); } class Consumer extends Thread{ @Override public void run() { while(true){ try { //从阻塞队列中取出一个元素 queue.take(); System.out.println("队列剩余" + queue.size() + "个元素"); } catch (InterruptedException e) { } } } } class Producer extends Thread{ @Override public void run() { while (true) { try { //向阻塞队列中插入一个元素 queue.put(1); System.out.println("队列剩余空间:" + (size - queue.size())); } catch (InterruptedException e) { } } } } }
ThreadLocal的设计理念与做用 ThreadLocal的做用是提供线程内的局部变量,在多线程环境下访问时能保证各个线程内的ThreadLocal变量各自独立。也就是说,每一个线程的ThreadLocal变量是本身专用的,其余线程是访问不到的。ThreadLocal最经常使用于如下这个场景:多线程环境下存在对非线程安全对象的并发访问,并且该对象不须要在线程间共享,可是咱们不想加锁,这时候可使用ThreadLocal来使得每一个线程都持有一个该对象的副本。
concurrent包的总体架构
ArrayBlockingQueue, CountDownLatch类的做用
CountDownLatch:容许线程集等待直到计数器为0。适用场景: 当一个或多个线程须要等待指定数目的事件发生后再继续执行。
ArrayBlockingQueue: 一个基于数组实现的阻塞队列,它在构造时须要指定容量。当试图向满队列中添加元素或者从空队列中移除元素时,当前线程会被阻塞。经过阻塞队列,咱们能够按如下模式来工做:工做者线程能够周期性的将中间结果放入阻塞队列中,其它线程能够取出中间结果并进行进一步操做。若工做者线程的执行比较慢(还没来得及向队列中插入元素),其余从队列中取元素的线程会等待它(试图从空队列中取元素从而阻塞);若工做者线程执行较快(试图向满队列中插入元素),则它会等待其它线程取出元素再继续执行。
wait(),sleep() 的区别 wait():Object类中定义的实例方法。在指定对象上调用wait方法会让当前线程进入等待状态(前提是当前线程持有该对象的monitor),此时当前线程会释放相应对象的monitor,这样一来其它线程便有机会获取这个对象的monitor了。当其它线程获取了这个对象的monitor并进行了所需操做时,即可以调用notify方法唤醒以前进入等待状态的线程。
sleep():Thread类中的静态方法,做用是让当前线程进入休眠状态,以便让其余线程有机会执行。进入休眠状态的线程不会释放它所持有的锁。
线程池的用法与优点 优点: 实现对线程的复用,避免了反复建立及销毁线程的开销;使用线程池统一管理线程能够减小并发线程的数目,而线程数过多每每会在线程上下文切换上以及线程同步上浪费过多时间。
用法: 咱们能够调用ThreadPoolExecutor的某个构造方法来本身建立一个线程池。但一般状况下咱们可使用Executors类提供给咱们的静态工厂方法来更方便的建立一个线程池对象。建立了线程池对象后,咱们就能够调用submit方法提交任务到线程池中去执行了;线程池使用完毕后咱们要记得调用shutdown方法来关闭它。
for-each与常规for循环的效率对比 关于这个问题咱们直接看《Effective Java》给咱们作的解答:
for-each可以让代码更加清晰,而且减小了出错的机会。 下面的惯用代码适用于集合与数组类型:
for (Element e : elements) {
doSomething(e);
}
使用for-each循环与常规的for循环相比,并不存在性能损失,即便对数组进行迭代也是如此。实际上,在有些场合下它还能带来微小的性能提高,由于它只计算一次数组索引的上限。
简述Java IO与NIO的区别 Java IO是面向流的,这意味着咱们须要每次从流中读取一个或多个字节,直到读取完全部字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,而后对缓冲区中的数据进行相应处理。
Java IO是阻塞IO,而NIO是非阻塞IO。 Java NIO中存在一个称为选择器(selector)的东西,它容许你把多个通道(channel)注册到一个选择器上,而后使用一个线程来监视这些通道:若这些通道里有某个准备好能够开始进行读或写操做了,则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操做的线程能够去干别的事情。
反射的做用与原理 反射的做用归纳地说是运行时获取类的各类定义信息,好比定义了哪些属性与方法。原理是经过类的class对象来获取它的各类信息。
Java中的泛型机制 关于泛型机制的详细介绍请直接戳 Java核心技术点之泛型
常见设计模式 所谓“设计模式”,不过是面向对象编程中一些经常使用的软件设计手法,而且通过实践的检验,这些设计手法在各自的场景下能解决一些需求,所以它们就成为了现在广为流传的”设计模式“。也就是说,正式由于在某些场景下产生了一些棘手的问题,才催生了相应的设计模式。明确了这一点,咱们在学习某种设计模式时要充分理解它产生的背景以及它所解决的主要矛盾是什么。
经常使用的设计模式能够分为如下三大类: 建立型模式: 包括工厂模式(又可进一步分为简单工厂模式、工厂方法模式、抽象工厂模式)、建造者模式、单例模式。
结构型模式: 包括适配器模式、桥接模式、装饰模式、外观模式、享元模式、代理模式。
行为型模式: 包括命令模式、中介者模式、观察者模式、状态模式、策略模式。
注解的基本概念与使用 注解能够看做是“加强版的注释”,它能够向编译器、虚拟机说明一些事情。 注解是描述Java代码的代码,它可以被编译器解析,注解处理工具在运行时也可以解析注解。注解自己是“被动”的信息,只有主动解析它才有意义。 除了向编译器/虚拟机传递信息,咱们也可使用注解来生成一些“模板化”的代码。