java面试中面试官最喜欢随口问的问题,分享一下经验,百度出来的答案提供大家参考,记得一定要答出来,大概知道是什么,真的不懂也没关系。如有遗漏欢迎大家补充。
目录
StringBuilder 、 StringBuffer 、String的区别
抽象类abstractclass和接口interface的区别
重写(Overriding)和重载(Overloading)的区别
深拷贝和浅拷贝的区别
序列化和反序列化的区别
构造方法和普通方法(实例方法、类方法)的区别
静态变量和实例变量的区别
进程和线程的区别
集合和数组之间的区别
数组和链表的区别
堆heap和栈stack的区别
栈和队列的区别
ArrayList,LinkedList,Vector的区别
常见Map类的区别
Hashtable和HashMap的区别
迭代器Iterator和ListIterator的区别
快速失败(fail-fast)和安全失败(fail-safe)的区别
length和length(自动装拆箱)的区别
int和integer的区别
break、continue、return的区别
collection和collections的区别
erro和Excetion的区别
number和Math 的区别
Static Nested Class 和inner class的区别
final,finally,finalize的区别
IO模型:BIO、NIO、AIO的区别
Wait和Sleep的区别
强引用、软引用、弱引用、虚引用 的区别
for和wihile(含do while)的区别
forward 和 redirect 的区别
寄存器和程序计数器的区别
null和“”的区别
==和=的区别
>>和>>>的区别
+和+=的区别
==与equal的区别
&和&&的区别
|和||的区别
数组和String 有没有 length()这个方法?
String,StringBuffer与StringBuilder的区别
(阿里巴巴-蚂蚁金服务面试有问到)
String 字符串常量----- 不可变(不适应频繁修改,不适应循环修改),使用率95%
StringBuffer 字符串变量(线程安全)----可变
StringBuilder 字符串变量(非线程安全)----可变
速度方面:StringBuilder > StringBuffer > String
对于三者使用的总结:
1.如果要操作少量的数据用 = String
2.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer(线程安全)
3.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder(非线程安全)
https://blog.csdn.net/rmn190/article/details/1492013
abstractclass(抽象类)和interface(接口)的区别
真的是常问...
抽象类可以有抽象方法和普通方法,也可以有自己的数据成员. 接口只允许有常量,抽象方法和静态类成员.
抽象类不可以多继承. 接口可以被多继承,
抽象类被继承时如果有抽象方法没被重写,则子类也为抽象类. 接口被实现时,所有方法必须被重写.
- 接口中没有构造方式(因为接口不是类)
- 接口中的方法必须是抽象的(不能实现)
- 接口中除了static、final变量,不能有其他变量
- 接口支持多继承(一个类可以实现多个接口)
重写(Override)与重载(Overload)的区别
(迅雷--网心科技面试有问到)
总结:
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
- (1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
- (2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
- (3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
http://www.runoob.com/java/java-override-overload.html
深拷贝和浅拷贝的区别
(大疆一面有问到)
1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝(例:assign())
深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:JSON.parse()和JSON.stringify(),但是此方法无法复制函数类型)
总结:
浅拷贝就想是您和您的影子之间的关系 : 你挂了, 你的影子也跟着挂了
深拷贝就像是您的克隆人, 你挂啦, 可你的克隆人还活着
https://blog.csdn.net/github_37130188/article/details/99491744
序列化和反序列化的区别
什么是序列化?将对象转换为字节。
什么是反序列化?将字节转换回对象。
什么时候使用序列化?当我们想要持久化对象的时候。当我们希望对象存在于JVM的生存期之后。
记住:
序列化对象时,只保存对象的状态,而不保存对象的类文件或方法。
当您序列化一个2字节的对象时,您会看到51个字节的序列化文件。
把Java对象转换为字节序列,并存储至一个储存媒介的过程。
反序列化:把字节序列恢复为Java对象的过程。
简单说法是:序列化把当前对象信息保存下来。反序列化刚好相反的操作,即读取信息设置到当前对象上。
序列化作用:
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.通过序列化对象在网络中传递对象;
3.通过序列化在进程间传递对象。
构造方法和普通方法(实例方法、类方法)的区别
类方法,有static修饰符,典型的主函数
public static void main(String[] args){}
实例方法,就是一般的方法
构造方法,没有返回值(就是连void都没有),方法名与类名一样
public class Test{
public static void myMethod();//类方法
public void myMethod2();//实例方法
public Test(){}//构造方法,没有返回值,方法名与类名一样
}
构造方法:
①方法名和 类名相同(在java中普通函数可以和构造函数同名,但是必须带有返回值)
②在方法名的前面没有返回值类型的声明
③在方法中不能使用return语句返回一个值
④在创建对象时,要调用new,如:book b1=new book();
⑤当没有指定构造方法时,系统会自动添加无参的构造方法
⑥当有指定构造方法时,无论该构造方法是有参,还是无参,系统都不会再自动添加无参的构造方法
⑦构造方法的重载:方法名相同,但参数不同的多个方法,调用时会自动根据不同的参数选择相应的方法
普通方法有返回类型,方法名小写,不能和类名相同,如:void XX(){} 普通方法:代表对象可以干什么
构造方法是初始化对象的重要途径,如:student s=new student(); s这个实例,是通过构造方法初始化的 构造方法:可创建一个对象,并可初始化对象的值
构造方法有对类属性得初始化的功能,如:public people(String name){this name=name;}或public people(){name="zangsan";age=11;} 完成了people类属性name或age的初始化
https://www.cnblogs.com/zterry/p/6835417.html
https://www.cnblogs.com/fclbky/p/6424171.html
https://blog.csdn.net/weixin_41685497/article/details/79202034
静态变量和实例变量的区别
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
进程和线程区别
如果把进程比喻一个工厂,线程就是生产线,一个工厂可以有多个生产线;
一个程序至少有一个进程,一个进程至少有一个线程。
(1)定义:
进程:
进程就是在操作系统上执行的一个程序;比如:qq.exe。是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.(进程之间没有关系,都是相对独立的。每个进程独享一部分内存及其他系统资源。操作系统允许多进程(任务)处理模式)
线程:
线程是进程的一个实体表现。是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.(进程由多个线程组成。一个进程中的多个线程共享该进程的资源。一个进程中的多个线程支持并发(多线程))
优缺点:
线程和进程在使用上各有优缺点:
线程执行开销小,但不利于资源的管理和保护;
而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
区别:
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。
线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
关系:
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
集合和数组之间的区别
在 Java 中数组的长度是不可修改的。然而在实际应用的很多情况下,无法确定数据数量。这些数据不适合使用数组来保存,这时候就需要使用集合。
数组-->字符串 toString
字符串-->数组 split
数组:保存基本数据类型
集合:对象
数组-->集合 asList
集合-->数组 toArray
数组和链表的区别
概念:
数组:是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组。(用于访问数据,不做操作)
链表:恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起。比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一个元素。如果要访问链表中一个元素,需要从第一个元素开始,一直找到需要的元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以了。如果应用需要经常插入和删除元素你就需要用链表数据结构了。(用于经常操作)
区别:
1、从逻辑结构角度来看:
数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况(数据插入、删除比较麻烦)。当数据增加时,可能超出原先定义的元素个数(越界);当数据减少时,造成内存浪费。
链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。(数组中插入、删除数据项时,需要移动其它数据项)
2、数组元素在栈区,链表元素在堆区;
3、从内存存储角度来看:
(静态)数组从栈中分配空间, 对于程序员方便快速,但自由度小。
链表从堆中分配空间, 自由度大但申请管理比较麻烦。
数组利用下标定位,时间复杂度为O(1)【查找复杂度:O(1)】, 链表定位元素时间复杂度O(n)【查找复杂度:O(n)】;
数组插入或删除元素的时间复杂度O(n)【添加/删除复杂度:O(n)】,链表的时间复杂度O(1)【添加/删除复杂度:O(1)】.
堆和栈的区别
内存分为两种,一种是栈内存,另一种就是堆内存
堆是用来存放对象的,栈是用来存放执行程序的
两者的差异:
1.堆内存用来存放由new创建的对象和数组 VS 2.栈内存用来存放方法或者局部变量等
3.堆是先进先出/后进后出 VS 4.栈是先进后出/后进先出,是典型的数据结构
5.堆是所有线程共享它 VS 6.栈是每个线程就创建一个栈内存空间
两者的相同:
1.都是属于Java内存的一种
2.系统都会自动去回收它,但是对于堆内存一般开发人员会自动回收它
区别:
java中堆和栈的区别自然是面试中的常见问题,下面几点就是其具体的区别
1.各司其职:
最主要的区别就是栈内存用来存储局部变量和方法调用。
而堆内存用来存储Java中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。
2.独有还是共享:
栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。
而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。
3.异常错误:
如果栈内存没有可用的空间存储方法调用和局部变量,JVM会抛出java.lang.StackOverFlowError。
而如果是堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。
空间大小:
栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生StackOverFlowError问题。
你可以通过-Xss选项设置栈内存的大小。-Xms选项可以设置堆的开始时的大小,-Xmx选项可以设置堆的最大值。
这就是Java中堆和栈的区别。理解好这个问题的话,可以对你解决开发中的问题,分析堆内存和栈内存使用,甚至性能调优都有帮助。
查看默认值(Updated)
查看堆的默认值,使用下面的代码,其中InitialHeapSize为最开始的堆的大小,MaxHeapSize为堆的最大值。
看这:https://blog.csdn.net/github_37130188/article/details/99491588
https://blog.csdn.net/u011546655/article/details/52170470
https://blog.csdn.net/emira_j/article/details/51232611
栈和队列的区别
栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只是其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表。
(吃了吐是栈,吃了拉是队列)
LinkedList数据结构是一种双向的链式结构,每一个对象除了数据本身外,还有两个引用,分别指向前一个元素和后一个元素,和数组的顺序存储结构(如:ArrayList)相比,插入和删除比较方便,但速度会慢一些。
栈的定义
栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
(1)通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。
(2)当表中没有元素时称为空栈。
(3)栈为后进先出(Last In First Out)的线性表,简称为LIFO表。
栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,要到最后才能删除。
队列定义
队列(Queue)是只允许在一端进行插入,而在另一端进行删除的运算受限的线性表
(1)允许删除的一端称为队头(Front)。
(2)允许插入的一端称为队尾(Rear)。
(3)当队列中没有元素时称为空队列。
(4)队列亦称作先进先出(First In First Out)的线性表,简称为FIFO表。
//使用removeFirst()方法,返回队列中第一个数据,然后将它从队列中删除
https://blog.csdn.net/e421083458/article/details/12967121
堆、栈和队列的区别:
https://jingyan.baidu.com/article/546ae18566c6ce1149f28c36.html
ArrayList和LinkedList、Vector的区别
List接口下一共实现了三个类:ArrayList,LinkedList,Vector。
LinkedList主要保持数据的插入顺序的时候使用,采用链表结构。
ArrayList和LinkedListt的区别:
1.ArrayList查询快,增删慢;
因为ArrayList类的底层是采用动态数组进行数据管理的,
2.LinkedListt查询慢,增删块’
因为LinkedListt类的底层是采用链表进行数据管理的,
ArrayList,Vector主要区别为以下几点:
(1):Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
(2):ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
(3):Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。
总结:
如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
笼统来说:
ArrayList:查询快(有索引的存在)
LinkedList:增删改快
Vector是线程安全
ArrayList 源码分析请见 Java源码阅读之ArrayList
LinkedList 源码分析请见 Java源码阅读之LinkedList
同步性
Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。
数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。
使用模式
在ArrayList和Vector中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?
这意味着,你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作,你最好选择其他的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢-O(i),其中i是索引的位置.使用ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。LinkList也会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。
最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤其是对于执行效率要求高的程序更应如此。因为使用数组(Array)避免了同步、额外的方法调用和不必要的重新分配空间的操作。
https://blog.csdn.net/ldxlz224/article/details/52574821
https://www.cnblogs.com/zhangzongle/p/5432212.html
https://blog.csdn.net/tayanxunhua/article/details/10037403
常见的Map类的区别
HashMap和Hashtable的区别
Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。
hashmap可以看做是hashtable的替代 者,HashMap的Value和Key都可为NULL,而HashTable不可以,同时,HashTable是线程同步的,而HashMap不 是.HashTable用Iterator遍历,HashMap用Enumeration遍历.HashTable 中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。计算index的方 法不同,HashTable直接利用hashcode()得出,HashMap对hashcode重新计算得出.
https://blog.csdn.net/mynameishuangshuai/article/details/52748731
(实现原理):https://www.cnblogs.com/beatIteWeNerverGiveUp/p/5709841.html
迭代器Iterator和ListIterator的区别
Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历 ,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口 ,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
快速失败(fail-fast)和安全失败(fail-safe)的区别
快速失败:当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个集合时,就会抛出一个ConcurrentModification异常。 在java.util包下的都是快速失败。
安全失败:你在迭代的时候会去底层集合做一个拷贝,所以你在修改上层集合的时候是不会受影响的,不会抛出ConcurrentModification异常。 在java.util.concurrent包下的全是安全失败的。
length和length()的区别
数组没有length()方法,有length 的属性。String 有length()方法。JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆
int和Integer的区别
(迅雷-网心科技面试有问到)
int是基本数据类型;
integer是包装类(引用类型),自动封装和拆箱的概念;
自动封装: integer i =10; 相当于 integer i = new integer(10);
自动拆箱:integer m = 10;
int n = m;
相当于:n = m.intValue(10);
1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
自动装箱和拆箱就是基本类型和引用类型之间的转换,至于为什么要转换,因为基本类型转换为引用类型后,就可以new对象,从而调用包装类中封装好的方法进行基本类型之间的转换或者toString(当然用类名直接调用也可以,便于一眼看出该方法是静态的),还有就是如果集合中想存放基本类型,泛型的限定类型只能是对应的包装类型。
类似int的自动封装和拆箱关键字对应integer的基本类型还有:
boolean、byte、short、long、float、double,它们对于的Boolean、Byte、Short、Long、Float、Double (记忆:首字母大写)
只有int和char对应的特殊,char对应的是Character
https://www.cnblogs.com/guodongdidi/p/6953217.html
break和continue、return的区别
(请看例子对比结果就很清楚了)
break:强制当前循环终止,在哪个for就跳出哪个for,跳出for循环后继续下面的代码;
例子:
for(int i=0;i<10;i++){
if(i==6){
break;
}
system.out.println(i);
}
system.out.println(“hello”);
输出结果(不满足条件后停止循环,跳出循环,继续执行hello的代码):
0
1
2
3
4
5
hello
continue:跳出本次循环,直接执行接下来的循环;
例子:
for(int i=0;i<10;i++){
if(i==6){
continue;
}
system.out.println(i);
}
system.out.println(“hello”);
输出结果(continue输出结果没有6,除了这个,接下来还可以继续执行):
0
1
2
3
4
5
7
8
9
hello
return(类似break):从当前的方法退出,执行return后,该方法内后面剩余代码都不执行;
例子:
for(int i=0;i<10;i++){
if(i==6){
return;
}
system.out.println(i);
}
system.out.println(“hello”);
输出结果(不满足条件后,不仅结束循环,还结束循环后面的代码,后面的hello代码都不执行了):
0
1
2
3
4
5
collection和collections的区别。
(TCL-多媒体笔试有)
你千万别说一个是单数一个是复数。
collection是结合类的上级接口,子接口有List和Set等,Collections是java.util下的一个工具类,提供一些列静态方法对集合搜索排序线程同步化等.
异常(Throwable:error和Exception)的区别
为什么水的题最容易出现?
感觉这个题很水,要说C++的话有区别,感觉JAVA里区别 不大.反正中软的题目里我就瞎扯了.单纯从字面的角度去说,error就是严重的错误,像JVM产生的一些错误等,会停止程序运行或产生错误结 果.exception是一定程度上可预见的错误,可以捕获以及处理.其实error也可以捕获...
Throwable包含了错误(Error)和异常(Excetion两类) Exception又包含了运行时异常
Throwable是所有异常的根,java.lang.Throwable
Error是错误,java.lang.Error
Exception是异常,java.lang.Exception
https://blog.csdn.net/badguy_gao/article/details/78638688
Number & Math 类的区别
Number当需要使用数字的时候,我们通常使用内置数据类型,如:byte、int、long、double 等。
然而,在实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情形。为了解决这个问题,Java 语言为每一个内置数据类型提供了对应的包装类。
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
http://www.runoob.com/java/java-number.html
Static Nested Class 和inner class的不同
static nested class 指静态嵌套类,或称嵌套类,是C++中常用的说法,inner class指内部类,是JAVA中的说法.
StaticNestedClass 是被声明为静态(static)的内部类,它可以不依赖于外部类实例被
实例化。
而通常的inner class内部类需要在外部类实例化后才能实例化。
内部类是一个类内部类的统称,具体分为四种:成员类,方法类,静态成员类,局部类,匿名类.其中匿名类是局部类的特殊情况.对于成员类和静态成员类都存在于类的顶层代码中,相当于类的静态方法和非静态方法的关系,区别在于 成员类依赖于类实例而静态成员类不依赖.所以前者只能访问实例方法和成员而后者只能访问静态方法和成员.它们都用于创建一个只和当前类有关,和其它类无关 的依赖类.是否静态取决于是否依赖类的实例.局部类相当于局部变量,存在于类的局部代码中,相当于在main()中随意定义和使用类,唯一的不同是它只能 使用final型的局部变量,这和垃圾回收机制有关,即局部变量会在代码块结束后被回收,而对象不一定,所以对象只能使用final的局部变量,同样,局 部类存在的局部代码块也可以有静态和非静态的差别.局部类罪常见的应用就是匿名类.匿名类就是无名子的局部类,常在SWING设计中的添加监听中出现.
static nested class相当于inner class中的静态成员类.
实例代码就不贴了,太累,发个地址,这篇帖子说的相当详细,就是有点累赘.,请自行百度,java内部类的基础教学,或则看我的另篇文章找答案;
https://blog.csdn.net/bbs11007/article/details/78775992
final,finally,finalize的区别
final修饰符(关键字):如果一个类被申明为final,意味着它不能再派生出新的子类,不能作为父类被继承,因此一个类不能既被声明为abstract的,又被声明为final的。将变量和方法声明为final变量的,可以保证它们在使用中不被改变。被声明为final的变量必须在申明时给定初值,而在以后的引用中只能读取不可以被修改。被申明为final的方法也同样只能使用不能重载。
finally:在异常处理时提供finally块来执行任何清除操作。如果抛出一个异常,那么相匹配的catch子句就会执行,然后控制就会进入finally块(如果有的话)。
异常处理(try...catch...finally)时提供finally来执行任何清楚操作。无论是否如何都会转入finally块。
通常用于关闭资源、释放锁
finalize方法名:finalize方法在垃圾回收器执行内存对象清理。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。
如果内存足够,filalize()可能永远不被执行。
java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做好必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用的情况下对这个对象的调用。它是在object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。finalize()方法是在垃圾收集器删除对象之前对这个对象的调用。()
https://www.cnblogs.com/ktao/p/8586966.html
IO模型:BIO、NIO、AIO的区别
等待Wait 和 休眠Sleep 的区别
wait:可以用来指定时间也可以不指定。不指定时间,只能由notify或者notifyAll来唤醒
线程会释放执行权,而且线程会释放锁
sleep:必须指定时间,时间会自动从冻结状态转成运行状态(临时阻塞状态)
线程会释放执行权,但是不释放锁
强引用、软引用、弱引用、虚引用 的区别
测试下:
/*强引用*/
public static void main(String[] args){
ReferenceTest test = new ReferenceTest();
test.testStrongReference();//强引用 调用测试看看结果
}
结果:
很明显内容一下子飙升86%,CPU100%
报内存溢出的异常!
/*软强引用*/
public static void main(String[] args){
ReferenceTest test = new ReferenceTest();
test.testSoftReference();//软引用 调用测试看看结果
}
结果:
内存也是飙升到86%,它呢会稳定在这个值,因为在抛出xxx异常前被垃圾回收,没有报内存溢出的异常!
/*弱强引用*/
public static void main(String[] args){
ReferenceTest test = new ReferenceTest();
test.testWeakREference();//弱引用 调用测试看看结果
}
结果:
内存也是升高,但是没有如软引用这么高,也不会报任何异常(因为会回收掉)
/*虚强引用*/
public static void main(String[] args){
ReferenceTest test = new ReferenceTest();
test.testPhantomREference();//虚引用 调用测试看看结果
}
结果:
跟强引用一样抛出溢出异常,虽然虚引用是引用强度最弱的,不影响对象的生命周期,使用和不使用指向对象呗JVM回收没有任何区别,所以跟强引用是一样的
for和wihile(含do while)循环的区别,以及什么时候用哪个
知道执行次数的时候一般用for,当条件循环时一般用while。
1.两种循环在构造死循环时的区别
用while构造死循环时,一般会使用while(TRUE)来构造死循环;而用for来构造死循环时,则使用for(;;)来构造死循环。
这两个死循环的区别是:while循环里的条件被看成表达式,因此,当用while构造死循环时,里面的TRUE实际上被看成永远为真的表达式,这种情况容易产生混淆,有些工具软件如PC-Lint就会认为出错了,因此构造死循环时,最好使用for(;;)来进行。
2.两种循环在普通循环时的区别
对一个数组进行循环时,一般来说,如果每轮循环都是在循环处理完后才讲循环变量增加的话,使用for循环比较方便。
如果循环处理的过程中就要将循环变量增加时,则使用while循环比较方便。
还有在使用for循环语句时,如果里面的循环条件很长,可以考虑用while循环进行替代,使代码的排版格式好看一些。
* 一个需求:使用for循环和while循环都可以去实现,那么到底两者之间有什么区别?
* 从内存角度考虑:
* 局部变量在栈内存中存在,当for循环语句结束,那么变量会及时被gc(垃圾回收器)及时的释放掉,不浪费空间
* 如果使用循环之后还想去访问循环语句中控制那个变量,使用while循环
* 从应用场景角度考虑:
* 如果一个需求明确循环的次数,那么使用for循环(开发中使用for循环的几率大于while循环)
* 如果一个需求,不知道循环了多少次,使用while循环
用法:
for循环格式
for(初始化语句; 判断条件语句; 控制条件语句){
循环体语句;
}
while循环语句格式
初始化语句;
while(判断条件语句){
循环体语句;
控制条件语句;
}
区别:控制条件语句的变量,在for循环结束后,就不可以被访问了,而while循环还可以访问,如果你继续想使用该变量,则可以使用while循环,否则推荐使用for循环,原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
forward 和 redirect 的区别
forward 是服务器请求资源,服务器直接访问目标地址的 URL,把那个 URL 的响应内
容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从
哪儿来的,所以它的地址栏中还是原来的地址。
redirect 就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般
来说浏览器会用刚才请求的所有参数重新请求,所以 session,request 参数都可以获取。
寄存器和程序计数器的区别
寄存器是中央处理器内的组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。
计数器是一种最简单基本的运算,计数器就是实现这种运算的逻辑电路,计数器在数字系统中主要是对脉冲的个数进行计数,以实现测量、计数和控制的功能,同时兼有分频功能,计数器是由基本的计数单元和一些控制门所组成,计数单元则由一系列具有存储信息功能的各类触发器构成,这些触发器有RS触发器、T触发器、D触发器及JK触发器等。
计数器只能作为计数使用,寄存器可以存放任何数值,寄存器可以当计数器用,反之不能
null和“”的区别
NULL:代表声明了一个空对象,不是一个字符串,可以赋给任何对象。
" " :代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串。
String s=null; 只是定义了一个句柄,即你有了个引用,但是这个引用未指向任何内存空间
String s=" "; 这个引用已经指向了一块是空字符串的内存空间,是一个实际的东东了,所以你可以对它操作。
1、NULL:代表声明了一个空对象,不是一个字符串,可以赋给任何对象。
空字符:代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串。
2、String s=null; 只是定义了一个句柄,即你有了个引用,但是这个引用未指向任何内存空间。
String s=”“; 这个引用已经指向了一块是空字符串的内存空间,是一个实际的东东了,所以可以对它操作。
String s=”a”和String s=new String(“a”);是有本质上的区别的 :
(1) 前者是在字符串池里写入一个字符’a’,然后用s指向它; 后者是在堆上创建一个内容为”a”的字符串对象。
(2) String str=”aaa”; //于栈上分配内存 ;String str=new String(“aaa”); //于堆上分配内存
https://www.cnblogs.com/x_wukong/p/3619221.html
==和=有什么区别
=是赋值,让左边的值变成右边的,譬如x=3,就是让x的值为3。
==是真正的等于,判断左右是否相等,譬如if(x==3)x=4;意思是如果x的值等于3,那么就让x等于4。
>>和>>>的区别
>>:表示带符号右移。正数右移高位补0,负数右移高位补1。比如:
4 >> 1,结果是2;-4 >> 1,结果是-2。-2 >> 1,结果是-1。
>>>:表示无符号右移。也叫逻辑右移,无论是正数还是负数,高位通通补0。
对于正数而言,>>和>>>没区别。
对于负数而言,-2 >>> 1,结果是2147483647(Integer.MAX_VALUE),-1 >>> 1,结果是2147483647(Integer.MAX_VALUE)。
所以,要判断两个数符号是否相同时,可以这么干:
return ((a >> 31) ^ (b >> 31)) == 0;
+ 和 += 的区别
1) +: short s1 = 1; s1 = s1+1;有什么错?
+:在编译器将右边的表达式结果计算出来后,和左边的变量类型比较精度,如果左边的变量精度低于右边的结果的精度,编译器会显式的报错,告诉程序员去强制转型。(所以s1 = s1 + 1出错)最后将表达式的结果复制到变量所在的内存区。
+ 是会在把后面的数值赋值到前面的变量时检测类型是否相同( 非自动强制转换!)如果是高精度到低精度的,需要报错,告诉程序员会loss of data
2) +=: short s1 = 1; s1 += 1;有错吗?
+=:编译器自动隐式直接将+=运算符后面的操作数强制装换为前面变量的类型,然后在变量所在的内存区上直接根据右边的操作数修改左边变量内存存储的二进制数值(所以 s += 1不报错)最后达到和赋值运算符相同的目的。与前者相比,由于后者是位操作,效率也较前者高。
真正意义包含两个部分,一是“+”,就是通常所说的直接相加,二是改变结果的类型:将计算结果的类型转换为“+=”符号左边的对象的类型。
+= 会把后面的数值自动强制转换为前面的类型,然后在那快内存上直接修改数值;
==与equal的区别
==:是java中的一个运算符,传的是地址
equals:是java类中的一个方法,所有的java类中都封装了equals方法。equals方法在java顶层类Object中的实现如下
值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。传的是内容
==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
==比较的是2个对象的地址,而equals比较的是2个对象的内容。
显然,当equals为true时,==不一定为true;
https://blog.csdn.net/u010921701/article/details/52821843
https://www.cnblogs.com/pop822/p/6215040.html
&和&&的区别
&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作。
|与||的区别
|:无论左边是否为ture,都会检验右边 ,
||:则不会。|| 的执行效率会更高
后续持续添加,如有其他请评论区建议添加,谢谢!