Java面试知识点总结
Posted Ipeter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试知识点总结相关的知识,希望对你有一定的参考价值。
1、Java中的原始数据类型都有哪些,它们的大小及对应的封装类是什么? 原始数据类型 大小(byte) 对应封装类型 boolean 1或4 Boolean byte 1 Byte short 2 Short int 4 Integer long 8 Long float 4 Float double 8 Double char 2 Char 2、“==”与“equals()”区别 对于枚举类型和原始数据类型的相等性比较,应该使用"=="; 对于引用类型的相等性比较,应该使用equals方法。 //“==”对于基本数据类型,判断两个变量的值是否相等。 //“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。 总之: “==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】 equal用于比较两个对象的值是否相同【不是比地址】 【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。 "=="比"equal"运行速度快,因为"=="只是比较引用. 3、 Java中的四种引用及其应用场景是什么? 强引用: 通常我们使用new操作符创建一个对象时所返回的引用即为强引用 软引用: 若一个对象只能通过软引用到达,那么这个对象在内存不足时会被回收,可用于图片缓存中,内存不足时系统会自动回收不再使用的Bitmap 弱引用: 若一个对象只能通过弱引用到达,那么它就会被回收(即使内存充足),同样可用于图片缓存中,这时候只要Bitmap不再使用就会被回收 虚引用: 虚引用是Java中最“弱”的引用,通过它甚至无法获取被引用的对象,它存在的唯一作用就是当它指向的对象回收时,它本身会被加入到引用队列中,这样我们可以知道它指向的对象何时被销毁。 4、object中定义了哪些方法? clone();equals();hashCode();toString();notify();notifyAll();wait();finalize();getClass(); 5、hashCode的作用? 关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。 hashCode 的常规协定是: 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。 以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。) 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。 以上这段官方文档的定义,我们可以抽出成以下几个关键点: 1)、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的; 2)、如果两个对象相同,就是适用于equals(Java.lang.Object) 方法,那么这两个对象的hashCode一定要相同; 3)、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点; 4)、两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。 ==》hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。 6、ArrayList,LinkedList,Vector的区别? ArrayList: 内部采用数组存储元素,支持高效随机访问,支持动态调整大小 LinkedList: 内部采用链表来存储元素,支持快速插入/删除元素,但不支持高效地随机访问 Vector: 可以看作线程安全版的ArrayList 7、String,StringBuilder,StringBuffer区别 String: 不可变的字符序列,若要向其中添加新字符需要创建一个新的String对象 StringBuilder: 可变字符序列,支持向其中添加新字符(无需创建新对象) StringBuffer: 可以看作线程安全版的StringBuilder 8、Map,Set,List,Queue,Stack特点及用法 Map<K, V>: Java中存储键值对的数据类型都实现了这个接口,表示“映射表”。支持的两个核心操作是get(Object key)以及put(K key, V value),分别用来获取键对应的值以及向映射表中插入键值对。 Set<E>: 实现了这个接口的集合类型中不允许存在重复的元素,代表数学意义上的“集合”。它所支持的核心操作有add(E e),remove(Object o), contains(Object o),分别用于添加元素,删除元素以及判断给定元素是否存在于集中。 List<E>: Java中集合框架中的列表类型都实现了这个接口,表示一种有序序列。支持get(int index), add(E e)等操作。 Queue<E>: Java集合框架中的队列接口,代表了“先进先出”队列。支持add(E element), remove()等操作。 Stack<E>: Java集合框架中表示堆栈的数据类型,堆栈是一种“后进先出”的数据结构。支持push(E item), pop()等操作。 9、HashMap与HashTable区别 HashTable是线程安全的,而HashMap不是 HashMap中允许存在null键和null值,而HashTable中不允许 10、HashMap实现原理 HashMap的底层实现是“基于拉链法的散列表”。 11、ConcurrentHashMap的实现原理 ConcurrentHashMap是支持并发读写的HashMap,它的特点是读取数据时无需加锁, 写数据时可以保证加锁粒度尽可能的小。由于其内部采用“分段存储”,只需对要进行写操作的数据所在的“段”进行加锁。 12、TreeMap,LinkedHashMap,HashMap区别 HashMap的底层实现是散列表,因此它内部存储的元素是无序的; TreeMap的底层实现是红黑树,所以它内部的元素的有序的。排序的依据是自然序或者是创建TreeMap时所提供的比较器(Comparator)对象。 LinkedHashMap能够记住插入元素的顺序。 13、Collection与Collections区别 Collection<E>是Java集合框架中的基本接口; Collections是Java集合框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。 14、对于“try-catch-finally”,若try语句块中包含“return”语句,finally语句块会执行吗? 答案是会执行。只有两种情况finally块中的语句不会被执行: 调用了System.exit()方法; JVM“崩溃”了。 15、Override,Overload区别 Override表示“重写”,是子类对父类中同一方法的重新定义 Overload表示“重载”,也就是定义一个与已定义方法名称相同但签名不同的新方法 16、接口与抽象类的区别 接口是一种约定,实现接口的类要遵循这个约定;抽象类本质上是一个类,使用抽象类的代价要比接口大。接口与抽象类的对比如下: 抽象类中可以包含属性,方法(包含抽象方法与有着具体实现的方法),常量;接口只能包含常量和方法声明。 抽象类中的方法和成员变量可以定义可见性(比如public、private等);而接口中的方法只能为public(缺省为public)。 一个子类只能有一个父类(具体类或抽象类);而一个接口可以继承一个多个接口,一个类也可以实现多个接口。 子类中实现父类中的抽象方法时,可见性可以大于等于父类中的;而接口实现类中的接口 方法的可见性只能与接口中相同(public)。 17、静态内部类与非静态内部类的区别 静态内部类不会持有外部类的引用,而非静态内部类会隐式持有外部类的一个引用。 18、java中的多态原理 指父类的引用指向子类对象时,调用方法时会调用子类的实现而不是父类的实现。其关键在于“动态绑定”。 19、简述java中线程同步方法 volatile: Java Memory Model保证了对同一个volatile变量的写happens before对它的读; synchronized: 可以来对一个代码块或是对一个方法上锁,被“锁住”的地方称为临界区,进入临界区的线程会获取对象的monitor, 这样其他尝试进入临界区的线程会因无法获取monitor而被阻塞。由于等待另一个线程释放monitor而被阻塞的线程无法被中断。 ReentrantLock: 尝试获取锁的线程可以被中断并可以设置超时参数。 20、wait(),sleep()区别 wait(): Object类中定义的实例方法。在指定对象上调用wait方法会让当前线程进入等待状态(前提是当前线程持有该对象的monitor), 此时当前线程会释放相应对象的monitor,这样一来其它线程便有机会获取这个对象的monitor了。当其它线程获取了这个对象的monitor并进行了所需操作时, 便可以调用notify方法唤醒之前进入等待状态的线程。 sleep(): Thread类中的静态方法,作用是让当前线程进入休眠状态,以便让其他线程有机会执行。进入休眠状态的线程不会释放它所持有的锁。 21、线程池的用法与优势 优势: 实现对线程的复用,避免了反复创建及销毁线程的开销;使用线程池统一管理线程可以减少并发线程的数目, 而线程数过多往往会在线程上下文切换上以及线程同步上浪费过多时间。 用法: 我们可以调用ThreadPoolExecutor的某个构造方法来自己创建一个线程池。 但通常情况下我们可以使用Executors类提供给我们的静态工厂方法来更方便的创建一个线程池对象。创建了线程池对象后, 我们就可以调用submit方法提交任务到线程池中去执行了;线程池使用完毕后我们要记得调用shutdown方法来关闭它。 22、for-each与普通for循环效率对比 for-each能够让代码更加清晰,并且减少了出错的机会。下面的惯用代码适用于集合与数组类型: for (Element e : elements) { doSomething(e); } 使用for-each循环与常规的for循环相比,并不存在性能损失,即使对数组进行迭代也是如此。实际上,在有些场合下它还能带来微小的性能提升,因为它只计算一次数组索引的上限。 23、java IO与NIO区别 Java IO是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。 Java IO是阻塞IO,而NIO是非阻塞IO。 Java NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上,然后使用一个线程来监视这些通道: 若这些通道里有某个准备好可以开始进行读或写操作了, 则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。 24、反射作用与原理 反射的作用概括地说是运行时获取类的各种定义信息,比如定义了哪些属性与方法。 原理是通过类的class对象来获取它的各种信息。
以上是关于Java面试知识点总结的主要内容,如果未能解决你的问题,请参考以下文章