1、阐述下对象的自动装箱和拆箱 2
基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。
自动装箱是java编译器在java原生类型和对应的对象包装类型上做的自动转换。
自动装箱:Integer i = 1;其实编译器为你自动实现了:Integer i = Integer.valueOf(1);自动拆箱:Integer i = 1;int a = i;实际上执行了:int a = i.intValue();
复制代码
int与integer的区别:
int 是基本类型,直接存数值,进行初始化时int类的变量初始为0。
integer是对象,用一个引用指向这个对象,Integer的变量则初始化为null。
复制代码
2、switch支持的数据类型
包括byte、short、char、int 和 enum ,及包装类型Character、Byte、Short和Integer,java7后又加入了对String的支持。阐述下支持String的原理:使用字符串的hash值作为表达式的值,而由于相同哈希值的情况下仍存在冲突的可能,所有在case语句块时仍需要通过equals方法来判断相等。
复制代码
3、equals、==、hashCode:
== : 比较引用地址的相等或基本数据类型/枚举类型的相等Equal:对象的值情况的相等hashCode:返回对象的存储地址关系:两对象比较:euqals返回true时,hashCode也相等。hashCode相等时,equals返回不一定相等。instanceof: 判断对象类型5是否相等,当父、子类判断时存在单向情况。 对象判断equals方法:1、 == 判断引用地址 2、instanceof 判断类型 3、属性匹配4、自反性、对称性、传递性、一致性 5、重写hashcode
复制代码
甲学生的年龄 :16 ,学号: 12345 乙学生的年龄 :16, 学号: 54321 这样甲和乙的hashcode 重写方式一样的 1 + 2+ 3+ 4+ 5 +(16*1 )= 31 但是 12345 不equals 54321
4、创建对象:
主要有以下四种对象创建方式:
1、new 2、反射 (这俩要调用构造函数) 3、clone 4、 反序列化
其中:
克隆:通过实现Cloneable、Serializable(序列化、反序列化实现)来实现对象的克隆反射:该方式的表现主要有:1、运行时取得字段与方法和修改(包括常量) 2、创建对象原理:jvm通过字节码文件生成相应的对象或获取其信息优缺点:增加了程序设计的灵活性;性能消耗较大
复制代码
5、简述下多态,Java多态的实现原理?动态绑定的理解?:
1、面向对象的三大特性:封装、继承、多态。
2、多态的定义:同一消息可以根据函数调用的不同而采用多种不同的行为方式。(发送消息就是函数调用)
3、多态的作用:消除类型之间的耦合关系(解耦)。
4、三个必要条件: 一、要有继承; 二、要有重写; 三、父类引用指向子类对象。重载:同一类中,同名函数不同的参数形式,基于对象实际的类型来选择所调用的方法,达到动态绑定的目的。重写:父类、子类中,同名同参方法,重新定义方法实现。区别: 前者编译时多态性、后者运行时多态性(静态方法除外,多态是针对实例方法)
复制代码
将一个方法调用同一个方法主体关联起来被称作绑定,JAVA中分为 前期绑定和后期绑定(动态绑定或运行时绑定),
前期绑定: 在程序执行之前进行绑定(由编译器和连接程序实现)叫做前期绑定,因为在编译阶段被调用方法的直接地址就已经存储在方法所属类的常量池中了,程序执行时直接调用。
后期绑定: 含义就是在程序运行时根据对象的类型进行绑定,想实现后期绑定,就必须具有某种机制,以便在运行时能判断对象的类型,从而找到对应的方法,简言之就是必须在对象中安置某种“类型信”,JAVA中除了static方法、final方法(private方法属于)之外,其他的方法都是后期绑定。
Java技术----多态的实现原理
6、简述下抽象类和接口区别:
1、接口是对动作的抽象(实现),抽象类是对根源的抽象。(继承)
2、接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。
3、抽象类要被子类继承,接口要被类实现。
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象类里可以没有抽象方法
7、如果一个类里有抽象方法,那么这个类只能是抽象类抽象类:区别与普通的类,不能直接被实例化,可以有构造函数,并且子类可不实现其抽象方法。接口:修饰符为public、变量为final,没有实际的方法,可实现多继承。复制代码
抽象类的意义:
抽象方法:由abstract修饰的方法为抽象方法,抽象方法只有方法的定义,没有方法的实现。
抽象类:一个类中如果包含抽象方法,该类应该用abstract关键字声明为抽象类。
抽象类不可以实例化,即使一个类中没有抽象方法,也可以将其定义为抽象类意义:
a.为子类提供公共的方法
b.封装子类中重复内容(成员变量和方法)
c.定义有抽象方法,子类有不同的实现,
复制代码
7、简述public、protected、private、default 的区别:2
也叫 作用域修饰词public 作用范围:当前类、同一个包、子类、其他包;
protected 作用范围:当前类、同一个包、子类;
default 作用范围:当前类、同一个包;
private 作用范围:当前类;
复制代码
8、简述下创建线程的方式:
1、直接通过new thread 的方式;2、实现runnable接口;3、通过接口callable (callable能拿到返回值和抛出异常);4、通过线程池来生成线程;
复制代码
9、sleep、wait、yield、notify、notifyall:
sleep和yield区别:sleep 给予线程的运行机会 不考虑优先级,then 阻塞 yield:给优先级高的线程执行,然后进入就绪状态wait和sleep区别:wait:释放对象锁 object的方法 —> notifysleep:不释放锁 thread的方法两者都可通过interrupted 打断暂 notify和notifyall区别:notify:唤醒的某一线程去得到锁notifyall:唤醒所有等待线程去竞争锁wait/notify/notifyall : 它们都需在同步块中调用 ,均可释放对象锁;wait:立即释放控制权 然阻塞(需notify) notify:执行完再释放复制代码
10、synchronized 、Lock区别:
synchronized:关键字
Lock:对象 可控制获取锁的时间与获取锁的信息
手动释放锁、让线程响应中断、可知获得锁与否
多线程竞争较激烈时,Lock较优上下文切换:cpu控制权由一个正在运行的线程切换到另一个就绪状态的线程
复制代码
11、异常处理:
Error、Exception:
父类:Throwable :含异常出现时的log
Error:系统级错误,如OOM
Exception:需程序捕捉和处理的程序设计性错误被检查异常(throw、try catch)、运行时异常Throw:方法中抛出异常
Throws:申明异常
try catch finally:try中有return 会记录返回值 待finally执行完 返回值不变如finally中有return 则值会变finally:释放外部资源
复制代码
12、简述下JVM内存模型: 2
JVM的内存模型主要可以分为线程共享区和线程私有区,
线程共享区:java堆(放对象和数组、GC)、方法区(类信息、常量、静态变量等,永久代);
线程私有区:程序计数器(指示代码执行、无oom)、Java虚拟机栈(java方法调用)、native方法栈;
而每个线程都有自己的栈内存, 堆是共享的,线程会缓存对象到栈中使用,而volatile则可要求线程从内存中读取
复制代码
13、简述下GC机制:2
判断对象内存是否该被回收:JVM根据可达性分析(引用计数会出现互相引用的情况)
java内存回收算法大概可分为:分年代回收:年轻代(创建)、老年代(呆的久)、永久代标记-复制算法:区域分两块 一块使用另一块回收 交替使用空闲区满时 就被复制到老年代区标记-清除、标记-整理算法
复制代码
14、算法
排序(必须手写会)
//冒泡 排序
public static void BubbleSort(int [] arr){int temp;//临时变量for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。for(int j=arr.length-1; j>i; j--){if(arr[j] < arr[j-1]){temp = arr[j];arr[j] = arr[j-1];arr[j-1] = temp;}}}}复制代码
排序算法总结
查找()
复制代码
15、java中的基本数据类型?各占多少位?多少字节?取值范围?String是基本类型还是引用类型?
基本数据类型(8种):
1.Int 32 4 -2,147,483,648 ~ 2,147,483,647
2.Short 16 2 -32768 ~ 32678
3.long 64 8 -9,223,372,036,854,775,808~+9,223,372,036,854,775,807
4.float 32 4 -3,40292347E+38 ~ +3,40292347E+38
5.double 64 8 -1.79769313486231576E+308 ~ 1.79769313486231576E+308
6.char 16 2 ‘\u0000′ ~ ‘\uFFFF’
7.boolean 1 0.125 true/false
8.byte 8 1 -128 ~ 127String是引用类型,
复制代码
16、Java什么时候是值传递什么时候是引用传递?
值传递的时候,将实参的值,copy一份给形参;
引用传递的时候,将实参的地址值,copy一份给形参。
不管是值传递还是引用传递,形参拿到的仅仅是实参的副本,而不是实参本身。
复制代码
Java到底是值传递?还是引用传递?
17、String相关的。String常量池,StringBuffer,StringBuilder。String不可变的理解。String的intern方法不同版本的实现原理的区别。
String常量池:
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池。如果字符串已经存在池中,就返回池中的实例引用。如果字符串不在池中,就会实例化一个字符串并放到池中。 Java能够进行这样的优化是因为字符串是不可变的,可以不用担心数据冲突进行共享.
留意文章中的面试题: (貌似被虐过!!!) String之常量池小结
String常量池,StringBuffer,StringBuilder, CharSequence的区别:
1、执行效率 :StringBuilder > StingBuffer > String
2、String 字符串常量 不可变,(通过不断的创建新的对象修改长度)
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
3、String 、StringBuffer 、StringBuilder 都实现了:CharSequence接口。
a++与++a的区别,如果单独使用没有任何区别,如果在运算中就有区别了,
a++是先运算在赋值,
而++a是先赋值在运算!!
String不可变的理解:
举个例子:String str = "aa"; str = "aa"+"bb";
此时str的值为"aabb",但是"aabb"不是在开始的字符串"aa"后面直接连接的"bb",而是又新生成了字符串"aabb",字符串"aa"一旦被初始化,那么它的值不可能再改变了。
StringBuffer strb = StringBuffer("aa"); strb.append("bb");
此时的strb的值也为"aabb",但是"aabb"是直接在开始的字符串"aa"后面连接的“bb”,并没有生成新的字符串。String对象的底层实际上是一个char[]数组:
private final char value[];
用final修饰的对象值可变,但是引用不变,StringBuffer对象的底层也是一个char[]数组:
char[] value; 复制代码
为什么String对象不可变,而StringBuffer可变?
18、JAVA集合框架
-
Collection:存储单个数据或者对象。
- |-List:列表:
- |-LinkedList :基于链表的List
- |-ArrayList :基于数组的List
- |-SubList:一个List的视图
- |-Vector:一个线程安全的List
- |-Stack:栈
- **|-Queue:队列 ,通常作为数据存储结构,不作为操作容器。**集合框架中应用比较少,主要在在并发包(java.util.concurrent)中实现的阻塞队列(消息队列)。
- |-ArrayDeque:基于数组实现的尾插队列(包含head,tail头尾指针).
- |-PriorityQueue:基于数组的自排序优先级队列(基于数组实现存储的二叉树堆排)。
- |-Set:一个不允许重复数据的集合
- |-HashSet:基于Hash+数组+链表实现的Set。
- |-LinkedHashSet:一个基于LinkedHashMap实现的Set。
- |-TreeSet:一个基于TreeMap实现的Set。
- |-EnumSet:
- |-JumboEnumSet
- |-RegularEnumSet
- |-HashSet:基于Hash+数组+链表实现的Set。
- |-List:列表:
-
Map:存储一组K-V键值对。
- |-HashMap:基于Hash+数组+链表实现的Map。
- |-LinkedHashMap:基于HashMap实现的双向链表。LruCache实现基础
- |-HashTable:基于Hash+数组+链表实现的线程安全(sync)Map。
- |-TreeMap:基于红黑树实现的有序Map。
- |-WeakHashMap:K为弱引用的HashMap,使用中,若k没有被引用则会自动回收掉
- |-HashMap:基于Hash+数组+链表实现的Map。
集合框架中唯一的两个线程安全集合
Vector(Stack是Vector的子类也是安全的)
Hashtable
复制代码
ArrayList,LinkedList异同点:
- 相同点:
- List是数组的封装接口,所有实现类都可与数组转换,且进行index(索引下标)获取,对于ArrayList和LinkedList只不过是不同的实现方式
- 不同点:
- ArrayList是对数组的封装,使得对数组的操作更加方便,查询快,增删慢。LinkedList是链表的实现,增删快,查询慢
HashMap,HashTable中的关联和差异:
HashMap与HashTable最大的区别在于hashtable是线程安全的, hashMap K-V都可为null,hashTable K-V都不能够为null.
ArrayList和Vector的比较:
- 相同点: 两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,
- 不同点:
- Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的
- ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,Vector增长原来的一倍,ArrayList增加原来的0.5倍。
补充: 底部的数据结构?散列表冲突的处理方法,散列表是一个什么样的数据结构?HashMap是采用什么方法处理冲突的?
HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。
当程序执行 map.put(String,Obect)方法 时,系统将调用String的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法,都可通过该方法获得它的 hashCode 值。
得到这个对象的 hashCode 值之后,系统会根据该 hashCode 值来决定该元素的存储位置。
HashMap采用的链表法的方式,链表是单向链表。
链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位;当创建 HashMap 时,有一个默认的负载因子(load factor),其默认值为 0.75,
增大负载因子可以减少 Hash 表(就是那个 Entry 数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的的操作(HashMap 的 get() 与 put() 方法都要用到查询);
减小负载因子会提高数据查询的性能,但会增加 Hash 表所占用的内存空间。http://blog.csdn.net/u011202334/article/details/51498893
复制代码
集合面试题1 集合面试题2 集合框架 Java容器框架
19、Java容器相关的辅助类Arrays和Collections了解一下(看那个傻逼问!)。
- Array与Arrays的区别:
- Array :数组类 ,提供了动态创建和访问 Java 数组的方法。
- Arrays:工具类,该类中包含了一些方法用来直接操作数组,比如可直接实现数组的排序(sort())、搜索(binarySearch())等。
- Collection和Collections的区别:
- Collection:集合接口(集合类的一个顶级接口)
- Collections:集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
20、Java中final,finalize()和finally的区别:
- final:关键字,可以用于类,方法,变量前,用来表示该关键字修饰的类,方法,变量具有不可变的特性
- final关键字用于基本数据类型前:这时表明该关键字修饰的变量是一个常量,在定义后该变量的值就不能被修改。
- final关键字用于方法声明前:这时意味着该方法时最终方法,只能被调用,不能被覆盖,但是可以被重载。
- final关键字用于类名前:此时该类被称为最终类,该类不能被其他类继承。
- finalize():finalize方法来自于java.lang.Object,用于回收资源。
- 可以为任何一个类添加finalize方法。finalize方法将在垃圾回收器清除对象之前调用。 在实际应用中,不要依赖使用该方法回收任何短缺的资源,这是因为很难知道这个方法什么时候被调用。
- finally:当代码抛出一个异常时,就会终止方法中剩余代码的处理,并退出这个方法(代码块)的执行。 finally try catch 顺序问题
21、Java怎样开启一个线程。线程池是干什么的?有哪些常用的线程池?优缺点是什么?
开启线程的方式:
1、继承Thread类:
//1):定义一个类A继承于java.lang.Thread类.
class MusicThread extends Thread{ //2):在A类中覆盖Thread类中的run方法. public void run() { //3):在run方法中编写需要执行的操作 for(int i = 0; i < 50; i ++){ System.out.println("播放音乐"+i); } }
} public class ExtendsThreadDemo { public static void main(String[] args) { for(int j = 0; j < 50; j ++){ System.out.println("运行游戏"+j); if(j == 10){ //4):在main方法(线程)中,创建线程对象,并启动线程. MusicThread music = new MusicThread(); music.start(); } } } }
复制代码
2、实现Runnable接口:
//1):定义一个类A实现于java.lang.Runnable接口,注意A类不是线程类.
class MusicImplements implements Runnable{ //2):在A类中覆盖Runnable接口中的run方法. public void run() { //3):在run方法中编写需要执行的操作 for(int i = 0; i < 50; i ++){ System.out.println("播放音乐"+i); } }
} public class ImplementsRunnableDemo { public static void main(String[] args) { for(int j = 0; j < 50; j ++){ System.out.println("运行游戏"+j); if(j == 10){ //4):在main方法(线程)中,创建线程对象,并启动线程 MusicImplements mi = new MusicImplements(); Thread t = new Thread(mi); t.start(); } } } }
复制代码
3、直接在函数体使用(特殊的第二种):
void java_thread()
{ Thread t = new Thread(new Runnable(){ public void run(){ // run方法具体重写mSoundPoolMap.put(index, mSoundPool.load(filePath, index)); getThis().LoadMediaComplete(); }}); t.start();
}
复制代码
补:继承方式和实现方式的区别?(遇到过)
- 继承方式:
- 从设计上分析,Java中类是单继承的,如果继承了Thread了,该类就不能再有其他的直接父类了.
- 从操作上分析,继承方式更简单,获取线程名字也简单.(操作上,更简单)
- 从多线程共享同一个资源上分析,继承方式不能做到.
- 实现方式:
- 从设计上分析,Java中类可以多实现接口,此时该类还可以继承其他类,并且还可以实现其他接口,设计更为合理.
- 从操作上分析,实现方式稍微复杂点,获取线程名字也比较复杂,得使用Thread.currentThread()来获取当前线程的引用.
- 从多线程共享同一个资源上分析,实现方式可以做到(是否共享同一个资源).
线程池构成
- 线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务;
- 工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以循环的执行任务;
- 任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行,它主要规定了任务的入口,任务执行完后的收尾工作,任务的执行状态等;
- 任务队列(taskQueue):用于存放没有处理的任务。提供一种缓冲机制。
有哪些常用的线程池?优缺点是什么?
线程生命周期:
几个方法的比较:
-
Thread.sleep(long millis),thread 方法,一定是当前线程调用此方法,当前线程进入阻塞,但**不释放对象锁,millis后线程自动苏醒进入可运行状态。**作用:给其它线程执行机会的最佳方式。
-
obj.wait(),obj方法,当前线程调用对象的wait()方法,当前线程释放对象锁,进入等待队列。依靠notify()/notifyAll()唤醒或者wait(long timeout)timeout时间到自动唤醒。
-
Thread.yield(),一定是当前线程调用此方法,当前线程放弃获取的cpu时间片,**由运行状态变会可运行状态,让OS再次选择线程。**作用:让相同优先级的线程轮流执行,但并不保证一定会轮流执行。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。Thread.yield()不会导致阻塞。
-
t.join()/t.join(long millis),当前线程里调用其它线程1的join方法,当前线程阻塞,但不释放对象锁,直到线程1执行完毕或者millis时间到,当前线程进入可运行状态。
-
obj.notify() 唤醒在此对象监视器上等待的单个线程,选择是任意性的。notifyAll()唤醒在此对象监视器上等待的所有线程。
22、volidate关键字的作用?
- volatile关键字不但可以防止指令重排
- 保证线程访问的变量值是主内存中的最新值。
什么是单例模式? Volidate的原理和指令重排序
23、Java clone的使用。
Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone(); System.out.println(p);
System.out.println(p1); 打印结果:
//com.pansoft.zhangjg.testclone.Person@2f9ee1ac
//com.pansoft.zhangjg.testclone.Person@67f1fba0
复制代码
Java中的clone方法
24、Java反射机制
反射机制:是程序在运行时能够获取自身的信息。
在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
复制代码
提供的功能: 在运行时能够判断任意一个对象所属的类 在运行时构造任意一个类的对象 在运行时判断任意一个类所具有的成员变量和方法 在运行时调用任一对象的方法 在运行时创建新类对象
反射机制的优缺点:
- 优点:反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性
- 缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。
25、Java静态代理和动态代理
Java静态代理和动态代理
26、类的加载过程,Person person = new Person();为例进行说明
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个这个类的java.lang.Class对象,用来封装类在方法区类的对象。
类从被加载到内存开始,到卸载出内存为止,其整个生命周期: 加载,验证,准备,解析,初始化,使用,卸载
其中:验证,准备,解析三个阶段又统称为“连接”
类加载的过程:
包括:加载,验证,准备,解析和初始化等5个阶段。
阿里、百度 都问过 自己看着办!
27、什么是内部类?内部类的作用
1、内部类( Inner Class )就是定义在另外一个类里面的类。与之对应,包含内部类的类被称为外部类。2、作用:a.内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类b.内部类的方法可以直接访问外部类的所有数据,包括私有的数据c.内部类所实现的功能使用外部类同样可以实现,只是有时使用内部类更方便
复制代码
28、泛型通配符extends与super的区别:
<? extends T> 限定参数类型的上界:参数类型必须是T或T的子类型<? super T> 限定参数类型的下界:参数类型必须是T或T的超类型
复制代码
29、进程和线程的区别
1、一个程序至少有一个进程,一个进程至少有一个线程.
2、进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
3、每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中
复制代码
30、序列化的方式,以及Serializable 和Parcelable 的区别:
- Serializable和Parcelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用者两种序列化方式。
- Serializable 属于JAVA API,Parcelable 属于Android SDK,
- Serializable 序列化和反序列化过程需要大量的I/O操作,Parcelable 不需要。
- Serializable 开销大,效率低,Parcelable 反之。
- Serializable 序列化到本地或者通过网络传输, Parcelable 内存序列化
31、静态内部类与非静态内部类之间区别
非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。
复制代码
java中静态内部类的设计意图
32、Thread中start()和run()的区别;
start():作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。
run():和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),
而并不会启动新线程!
复制代码
java高级部分:都搞明白 就要30K吧!!!
- 哪些情况下的对象会被垃圾回收机制处理掉?
- 讲一下常见编码方式?
- utf-8编码中的中文占几个字节;int型几个字节?
- 静态代理和动态代理的区别,什么场景使用?
- Java的异常体系
- 谈谈你对解析与分派的认识。
- 修改对象A的equals方法的签名,那么使用HashMap存放这个对象实例的时候,会调用哪个equals方法?
- Java中实现多态的机制是什么?
- 如何将一个Java对象序列化到文件里?
- 说说你对Java反射的理解
- 说说你对Java注解的理解
- 说说你对依赖注入的理解
- 说一下泛型原理,并举例说明
- Java中String的了解
- String为什么要设计成不可变的?
- Object类的equal和hashCode方法重写,为什么?
https://www.jianshu.com/p/c70989bd5f29