第一部分语言基础
一、java的基本类型各占字节数,int、char、long各占多少字节数
答:1、boolean 未指定,至少一个字节。仅定义取字面值true和false。
2、byte 1字节
3、short & char 2字节
4、int & float 4字节
5、long & double 8字节
二、int和Integer的区别
答:1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
三. Switch能否用string做参数?
答:在jdk1.7版本以前,参数类型只能是short、byte、int、char可正常运行。而例如String,Long、Integer、double、float等则会报错。
而jdk1.7版本以后,参数类型除了之前可使用的外,String、Integer类、 Character类、枚举类型都可以正常运行。而Long、double、float依旧会报错。
四. java中= = 和equals和hashCode的区别
答:1、在java中= =是运算符,用于比较两个变量是否相等。
2、equals是Objec类的方法,用于比较两个对象是否相等,默认Object类的equals方法是比较两个对象的地址,跟= =的结果一样。
3、hashCode也是Object类的一个方法。返回一个离散的int型整数。在集合类操作中使用,为了提高查询速度。(HashMap,HashSet等)
五、静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
答:可继承 不可重写 而是被隐藏
如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为"隐藏"。如果你想要调用父类的静态方法和属性,直接通过父类名.方法或变量名完成。
六、什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用
答:1、定义:在java语言中,可以吧一个类定义到另外一个类的内部,在类里面的这个类就叫内部类;
2、静态内部类是指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。静态内部类不可以有与外部类有相同的类名。不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型)
一个 静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法、
3、局部内部类 就是定义在一个代码块的内类,他的作用范围是所在代码块,是内部类中最少使用的一类型。局部内部类跟局部变量一样,不能被public ,protected,private以及static修饰,只能访问方法中定义final类型的局部变量。
4、匿名内部类是一种没有类名的内部类,不使用class,extends,implements,没有构造函数,他必须继承其他类或实现其他接口。匿名内部类的好处是使代码更加简洁,紧凑,但是带来的问题是易读性下降。他一般应用于GUI编程来实现时间处理等 。
在使用匿名内部类时,需要牢记以下几个原则。
1)内部类没有构造方法
2)匿名内部类不能定义静态成员,方法和类
3)匿名内部类不能是public protected private static
4)只能创建匿名内部类的一个实例
5)一个匿名内部类可以在new后面,这个匿名类必须继承一个父类或实现接口
6)因为匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效
七、抽象类和接口
答:一)、抽象类和接口区别
- 抽象类通过 abstract 关键字来定义,然后子类通过 extends 继承该抽象类后并实现相应抽象方法;接口通过 interface 关键字来定义,子类通过 implements 来实现该接口中的所有方法。
- 抽象类中的抽象方法可以使用 public、protected、default 修饰符;接口中的抽象方法默认并只能是 public,并且成员变量默认为 public static final 修饰的,所以我们可以直接通过 接口名.成员变量 使用它。
- 抽象类中允许有非抽象的方法和成员变量包括构造方法; 接口中的方法全是抽象的,不能有方法的实现。
- 子类只能通过继承来实现抽象类,由于 java 中的单继承特性,就导致只能继承一个抽象类;但是子类可以实现一个或多个接口,在一定程度上,这就解决了由于单继承特性所带来的问题。
- 从作用上来看,抽象类是为了把相同的东西提取出来,即重用;接口是为了把程序进行模块化,可以降低程序的耦合。
二)、抽象类的意义
Java中抽象类对于代码的维护和重用有很好的帮助,也是Java面向对象的一个重要体现。
三)、抽象类与接口的应用场景抽象类的应用场景:
a. 在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。
b. 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性。
接口的应用场景:
a. 一般情况下,实现类和它的抽象类之前具有 “is-a” 的关系,但是如果我们想达到同样的目的,但是又不存在这种关系时,使用接口。
b. 由于 java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,此时可以使用接口。
在使用中抽象类和接口我们该如何选择?
- 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
- 如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
- 如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。
四)、抽象类是否可以没有方法和属性?
抽象类中可以没有抽象方法,但有抽象方法的一定是抽象类。所以,java中 抽象类里面可以没有抽象方法。注意即使是没有抽象方法和属性的抽象类,也不能被实例化。
五)、接口的意义
1、重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制。正是由于这两种机制的存在,才赋予了Java强大的 面向对象能力。
2、简单、规范性:如果一个项目比较庞大,那么就需要一个能理清所有业务的架构师来定义一些主要的接口,这些接口不仅告诉开发人员你需要实现那些业务,而且也将命名规范限制住了(防止一些开发人员随便命名导致别的程序员无法看明白)。
3、维护、拓展性:比如你要做一个画板程序,其中里面有一个面板类,主要负责绘画功能,然后你就这样定义了这个类,可是在不久将来,你突然发现这个类满足不了你了,然后你又要重新设计这个类,更糟糕是你可能要放弃这个类,那么其他地方可能有引用他,这样修改起来很麻烦,如果你一开始定义一个接口,把绘制功能放在接口里,然后定义类时实现这个接口,然后你只要用这个接口去引用实现它的类就行了,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。
4、安全、严密性:接口是实现软件松耦合的重要手段,它描叙了系统对外的所有服务,而不涉及任何具体的实现细节。这样就比较安全、严密一些(一般软件服务商考虑的比较多)。
八、泛型中extends和super的区别
答: <? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入 <? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收 ? 既不能用于入参也不能用于返参
九、哪些情况下的对象会被垃圾回收机制处理掉?
答:1.所有实例都没有活动线程访问。
2.没有被其他任何实例访问的循环引用实例。
3.Java 中有不同的引用类型。判断实例是否符合垃圾收集的条件都依赖于它的引用类型。
要判断怎样的对象是没用的对象。这里有2种方法:
1.采用标记计数的方法:
给内存中的对象给打上标记,对象被引用一次,计数就加1,引用被释放了,计数就减一,当这个计数为0的时候,这个对象就可以被回收了。当然,这也就引发了一个问题:循环引用的对象是无法被识别出来并且被回收的。所以就有了第二种方法:
2.采用根搜索算法:
从一个根出发,搜索所有的可达对象,这样剩下的那些对象就是需要被回收的
十. Object有哪些公用方法?
十一. Java的四种引用,强弱软虚,用到的场景。
十二. HashCode的作用
十三. ArrayList、LinkedList、Vector的区别
三十三、Java
1、线程中sleep和wait的区别
(1)这两个方法来自不同的类,sleep是来自Thread,wait是来自Object;
(2)sleep方法没有释放锁,而wait方法释放了锁。
(3)wait,notify,notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。
2、Thread中的start()和run()方法有什么区别
start()方法是用来启动新创建的线程,而start()内部调用了run()方法,这和直接调用run()方法是不一样的,如果直接调用run()方法,
则和普通的方法没有什么区别。
3、关键字final和static是怎么使用的。
final:
1、final变量即为常量,只能赋值一次。
2、final方法不能被子类重写。
3、final类不能被继承。
三十四static:
1、static变量:对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,
在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
2、static代码块
static代码块是类加载时,初始化自动执行的。
3、static方法
static方法可以直接通过类名调用,任何的实例也都可以调用,因此static方法中不能用this和super关键字,
不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
三十五、String、StringBuffer和StringBuilder区别
- 1、三者在执行速度上:StringBuilder > StringBuffer > String ;
2、由于String是常量,不可改变,拼接时会重新创建新的对象;
3、StringBuffer是线程安全的,StringBuilder是线程不安全的;(由于StringBuffer有缓冲区)
十五、String为什么要设计成不可变的?
1、字符串池的需求
字符串池是方法区(Method Area)中的一块特殊的存储区域。当一个字符串已经被创建并且该字符串在 池 中,该字符串的引用会立即返回给变量,而不是重新创建一个字符串再将引用返回给变量。如果字符串不是不可变的,那么改变一个引用(如: string2)的字符串将会导致另一个引用(如: string1)出现脏数据。
2、允许字符串缓存哈希码
在java中常常会用到字符串的哈希码,例如: HashMap 。String的不变性保证哈希码始终一,因此,他可以不用担心变化的出现。 这种方法意味着不必每次使用时都重新计算一次哈希码——这样,效率会高很多。
3、安全
String广泛的用于java 类中的参数,如:网络连接(Network connetion),打开文件(opening files )等等。如果String不是不可变的,网络连接、文件将会被改变——这将会导致一系列的安全威胁。操作的方法本以为连接上了一台机器,但实际上却不是。由于反射中的参数都是字符串,同样,也会引起一系列的安全问题。
十六. try catch finally,try里有return,finally还执行么?
十七、final,finally,finalize的区别
答:final:修饰类、成员变量和成员方法,类不可被继承,成员变量不可变,成员方法不可重写
finally:与try…catch…共同使用,确保无论是否出现异常都能被调用到
finalize:类的方法,垃圾回收之前会调用此方法,子类可以重写finalize()方法实现对资源的回收
十八. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。
十九. Java面向对象的三个特征与含义。
二十. Override和Overload的含义去区别。
二十一. Interface与abstract类的区别。
二十二. Static class 与non static class的区别。
二十三. java多态的实现原理。
四十一. foreach与正常for循环效率对比。
答:使用for,更高效率。 使用foreach,更安全。
如果在使用foreach遍历对象的过程中,其他线程修改了List的内容,例如添加或者删除,就会出现不可知的错误,而使用foreach则能够正确抛出错误信息。
四十二. 反射的作用与原理。
答:1)、反射的作用
在JAVA中,只有给定类的名字,就可以通过反射机制来获取类的所有信息,可以动态的创建对象和编译。
2)、反射的原理
JAVA语言编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。
反射的实现主要借助以下四个类:
Class:类的对象
Constructor:类的构造方法
Field:类中的属性对象
Method:类中的方法对象
四十三. 泛型常用特点,List能否转为List。
四十四. 解析XML的几种方式的原理与特点:DOM、SAX、PULL。
第二部分Java深入源码
哪些情况下的对象会被垃圾回收机制处理掉?
讲一下常见编码方式?
utf-8编码中的中文占几个字节;int型几个字节?
静态代理和动态代理的区别,什么场景使用?
Java的异常体系
谈谈你对解析与分派的认识。
修改对象A的equals方法的签名,那么使用HashMap存放这个对象实例的时候,会调用哪个equals方法?
Java中实现多态的机制是什么?
如何将一个Java对象序列化到文件里?
说说你对Java反射的理解
说说你对Java注解的理解
说说你对依赖注入的理解
说一下泛型原理,并举例说明
Java中String的了解
String为什么要设计成不可变的?
Object类的equal和hashCode方法重写,为什么?
第二部分Java数据结构
常用数据结构
HashMap和HashTable的区别?和 ConcurrentHashMap 区别?和LinkedHashMap区别?内部实现原理?
LRUCache的原理?
ArrayList和LinkedList区别?为什么ArrayList不是线程安全的?
数据库的索引用的什么数据结构?
十四、List,Set,Map的区别
Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。 Set接口主要实现了两个实现类:HashSet: HashSet类按照哈希算法来存取集合中的对象,存取速度比较快
TreeSet :TreeSet类实现了SortedSet接口,能够对集合中的对象进行排序。
List的特征是其元素以线性方式存储,集合中可以存放重复对象。
ArrayList() : 代表长度可以改变得数组。可以对元素进行随机的访问,向ArrayList()中插入与删除元素的速度慢。
LinkedList(): 在实现中采用链表数据结构。插入和删除速度快,访问速度慢。
Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
HashMap:Map基于散列表的实现。插入和查询“键值对”的开销是固定的。可以通过构造器设置容量capacity和负载因子load factor,以调整容器的性能。
LinkedHashMap: 类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
TreeMap : 基于红黑树数据结构的实现。查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。
WeakHashMao :弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。
十五、ArrayMap和HashMap的对比
1、存储方式不同
HashMap内部有一个HashMapEntry<K, V>[]对象,每一个键值对都存储在这个对象里,当使用put方法添加键值对时,就会new一个HashMapEntry对象,
2、添加数据时扩容时的处理不一样,进行了new操作,重新创建对象,开销很大。ArrayMap用的是copy数据,所以效率相对要高。
3、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间
4、ArrayMap采用二分法查找;
十六、HashMap和HashTable的区别
1 、HashMap不是线程安全的,效率高一点、方法不是Synchronize的要提供外同步,有containsvalue和containsKey方法。
2、hashtable是,线程安全,不允许有null的键和值,效率稍低,方法是Synchronize的。有contains方法方法。Hashtable 继承于Dictionary 类
十七、HashMap与HashSet的区别
1、hashMap:HashMap实现了Map接口,HashMap储存键值对,使用put()方法将元素放入map中,HashMap中使用键对象来计算hashcode值,HashMap比较快,因为是使用唯一的键来获取对象。
2、HashSet实现了Set接口,HashSet仅仅存储对象,使用add()方法将元素放入set中,HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false。HashSet较HashMap来说比较慢。
十八、HashSet与HashMap怎么判断集合元素重复?
HashSet不能添加重复的元素,当调用add(Object)方法时候,
首先会调用Object的hashCode方法判hashCode是否已经存在,如不存在则直接插入元素;如果已存在则调用Object对象的equals方法判断是否返回true,如果为true则说明元素已经存在,如为false则插入元素。
十九、ArrayList和LinkedList的区别,以及应用场景
ArrayList是基于数组实现的,ArrayList线程不安全。
LinkedList是基于双链表实现的:
使用场景:
(1)如果应用程序对各个索引位置的元素进行大量的存取或删除操作,ArrayList对象要远优于LinkedList对象;
( 2 ) 如果应用程序主要是对列表进行循环,并且循环时候进行插入或者删除操作,LinkedList对象要远优于ArrayList对象;
二十. Map、Set、List、Queue、Stack的特点与用法。
二十一. HashMap和HashTable的区别。
二十二. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
二十三. TreeMap、HashMap、LindedHashMap的区别。
二十四. Collection包结构,与Collections的区别。
二十五、并发集合了解哪些?
1、java提供了一些可以用于并发程序中的数据集合,他们不会引起任何问题,一般来说,java提供了两类适用于并发应用的集合:
(1)阻塞式集合(blocking collection):这类集合包括添加和移除数据的方法。当集合已满或者为空时,被调用的添加或者 移除方法就不能立即执行,那么调用这个饭方法的线程将被阻塞,一直到该方法可以被成功执行。
(2)非阻塞式集合(Non-blocking collection):这类集合也包括添加和移除数据的方法。如果集合已满或者为空时,在调用添加或者移除方法时会返回null或者抛出异常,但是调用这个方法的线程不会被阻塞。
2、常用的并发集合类
ConcurrentHashMap:线程安全的HashMap的实现
CopyOnWriteArrayList:线程安全且在读操作时无锁的ArrayList
CopyOnWriteArraySet:基于CopyOnWriteArrayList,不添加重复元素
ArrayBlockingQueue:基于数组、先进先出、线程安全,可实现指定时间的阻塞读写,并且容量可以限制
LinkedBlockingQueue:基于链表实现,读写各用一把锁,在高并发读写操作都多的情况下,性能优于ArrayBlockingQueue
扩展:1、原子类
AtomicInteger:线程安全的Integer,基于CAS(无阻塞,CPU原语),优于使用同步锁的Integer
2、线程池
ThreadPoolExecutor:一个高效的支持并发的线程池,可以很容易的讲一个实现了Runnable接口的任务放入线程池执行,但要用好这个线程池,必须合理配置corePoolSize、最大线程数、任务缓冲队列,以及队列满了+线程池满时的回绝策略,一般而言对于这些参数的配置,需考虑两类需求:高性能和缓冲执行。
Executor:提供了一些方便的创建ThreadPoolExecutor的方法。
FutureTask:可用于异步获取执行结果或取消执行任务的场景,基于CAS,避免锁的使用
3、锁
ReentrantLock:与synchronized效果一致,但是又更加灵活,支持公平/非公平锁、支持可中断的锁、支持非阻塞的tryLock(可超时)、支持锁条件等,需要手工释放锁,基于AbstractQueueSynchronizer
ReentrantReadWriteLock:与ReentrantLock没有关系,采用两把锁,用于读多写少的情形
二十六、容器类介绍以及之间的区别
Java容器主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)
具体查看:http://alexyyek.github.io/2015/04/06/Collection/
二十七、List,Set,Map的区别
二十八、List和Map的实现方式以及存储方式
二十九、HashMap的实现原理
三十、HashMap数据结构?
三十一、HashMap源码理解
三十二、HashMap如何put数据(从HashMap源码角度讲解)?
三十三、HashMap怎么手写实现?
三十四、ConcurrentHashMap的实现原理
三十五、ArrayMap和HashMap的对比
三十六、HashTable实现原理
三十七、TreeMap具体实现
三十八、HashMap和HashTable的区别
三十九、HashMap与HashSet的区别
四十、HashSet与HashMap怎么判断集合元素重复?
四十一、集合Set实现Hash怎么防止碰撞
四十二、ArrayList和LinkedList的区别,以及应用场景
43.Java 中内部类为什么可以访问外部类
5、Java中重载和重写的区别:
1、重载:一个类中可以有多个相同方法名的,但是参数类型和个数都不一样。这是重载。
2、重写:子类继承父类,则子类可以通过实现父类中的方法,从而新的方法把父类旧的方法覆盖。
12.一个语言的编译过程
1.词法分析:将一串文本按规则分割成最小的结构,关键字、标识符、运算符、界符和常量等。一般实现方法是自动机和正则表达式
2.语法分析:将一系列单词组合成语法树。一般实现方法有自顶向下和自底向上
3.语义分析:对结构上正确的源程序进行上下文有关性质的审查
4.目标代码生成
5.代码优化:优化生成的目标代码,
二十五、谈谈NIO的理解