abstract class和interface是Java语⾔言中对于抽象类定义进⾏行行⽀支持的两种机制,正是由于这两种机制的存 在,才赋予了了Java强⼤大的⾯面向对象能⼒力力。
接口跟抽象类的区别
抽象类只能是单继承的,否则讲究产生致命方块问题,但需要实现多个的时候,可以使用接口
从语法方面说:定义接口的关键字是interface,定义抽象类的关键字是abstract
动态代理跟静态代理的区别?
从编程方面说:一个类只能使用一次继承关系,但一个类却可以实现多个接口,因为Java只支持单继承,多继承会造成致命方块问题
同时抽象类具有默认行为,即子类可以继承其默认方法,这样可以避免继承它的子类重复写相同的代码,但接口却不能拥有默认行为,但这也会造成当抽象类需要修改方法的时候继承它的子类也需要跟着改变
从设计理念上说,抽象类中的父类跟子类更多的是什么是什么的关系,即父类跟子类在 概念本质上相同的,而接口中的则不然,接口更多体现的是什么像什么的关系,并不要 求接口的实现跟接口的定义在本质上是相同的,仅仅需要实现接口定义的契约
什么是静态?什么是动态?
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理 类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。
静态代理总结:
优点:可以做到在不修改目标对象的功能前提下,对目标功能扩展.
缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同 时,一旦接口增加方法,目标对象与代理对象都要维护.
动态代理有以下特点:
1.代理对象,不需要实现接口
2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创 建代理对象/目标对象实现的接口的类型)
3.动态代理也叫做:JDK代理,接口代理
有那些数据结构?怎么使用?
Java接口方法能用那些修饰符?
public, abstract, default, static and strictfp修饰符可以修饰方法
Java中有哪些锁
一、 公平锁/非公平锁
二、可重入锁
三、独享锁/共享锁
四、互斥锁/读写锁
五、乐观锁/悲观锁
乐观锁与悲观锁不是指具体的什么类型的锁,而是指看待并发同步的角度。
悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会 认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为, 不加锁的并发操作一定会出问题。
乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候, 会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有 事情的。
从上面的描述我们可以看出,悲观锁适合写操作非常多的场景,乐观锁适合读操作非 常多的场景,不加锁会带来大量的性能提升。
六、分段锁
七、偏向锁/轻量级锁/重量级锁
八、自旋锁
TCP与UDP的区别
1、连接方面区别
TCP面向连接(如打电话要先拨号建立连接)。
UDP是无连接的,即发送数据之前不需要建立连接。
2、安全方面的区别
TCP提供可靠的服务,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到 达。
UDP尽最大努力交付,即不保证可靠交付。
3、传输效率的区别
TCP传输效率相对较低。
UDP传输效率高,适用于对高速传输和实时性有较高的通信或广播通信。
4、连接对象数量的区别
TCP连接只能是点到点、一对一的。
UDP支持一对一,一对多,多对一和多对多的交互通信。
什么是面向对象程序设计?
面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程架构。
面向对象程序设计方法是尽可能模拟人类的思维方式,使得软件的开发方法与过程尽可能接近人类认识世界、解决现实问题的方法和过程,也即使得描述问题的问题空间与问题的解决方案空间在结构上尽可能一致,把客观世界中的实体抽象为问题域中的对象。
面向对象程序设计以对象为核心,该方法认为程序由一系列对象组成。类是对现实世界的抽象,包括表示静态属性的数据和对数据的操作,对象是类的实例化。对象间通过消息传递相互通信,来模拟现实世界中不同实体间的联系。在面向对象的程序设计中,对象是组成程序的基本模块
基本数据类型:
1 Boolean型
2 整型1 int 2 short 3 long 4 byte
3 浮点型 float double
4 字符型 char
==跟equal的区别?
== 比较的是对象或引用的地址
equal()比较的是该对象或引用的值.
异常的分类:
1. 编译期异常
编译期的异常我们必须处理,如果我们不处理就会编译失败。我们必须通过程序来 处理编译期的异常
我们两种解决方案:抛出异常,把异常抛给调用当前方法的层内部处理,catch来 处理。
2. 运行期异常
编译的时候可以通过,但是在运行的时候产生的异常叫做运行期异常。
所有RuntimeException的子类都是运行期的异常
1 NollPointException 空指针异常,找不到对象
2 ClaaNotFoundException 指定类找不到异常,类不存在或地址错了
3 ArrayIndexOutBoundsException 数组下标越界异常
4 NoSuchMethodSrror 找不到指定方法异常
5 IndexOutBoundsException 索引越界异常
6 NumberFormatException 数字格式异常
7 SQLException Sql语句执行异常
8 IOException 输入输出异常
谈谈你对Java平台的理解。
答:Java首先是一种面向对象的语言,语言特性有封装,继承,多态,泛型,Lamda表达式等;
第二个特性:支持跨平台,一次书写导出运行(write once,run anywhere),能够实现跨平台是因为JVM,编写源文件,
通过javac编译成字节码.class文件,然后JVM再翻译成对应的机器码来运行;
第三个特性:垃圾回收器(GC),程序员不用关注内存的分配和回收。
JRE是Java运行时环境,JDK包含JRE,并提供了很多工具,包括编译器,诊断工具如Jconsole,visualVM等
字符串常用方法
char charAt (int index) 返回index所指定的字du符
String concat(String str) 将两字符串连接
boolean endsWith(String str) 测试字符串是否以str结尾
boolean equals(Object obj) 比较两对象
boolean startsWith(String str) 测试字符串是否以str开始
int length() 返回字符串的长度
String replace(char old ,char new) 将old用new替代
String toLowerCase() 将字符串内的字符改写成小写
String toUpperCase() 将字符串内的字符改写成大写
String substring(int1,int2) 取出字符串内第int1位置到int2的字符串
关于死锁的问题
在有些情况下死锁是可以避免的。三种用于避免死锁的技术:
加锁顺序(线程按照一定的顺序加锁)
加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
死锁检测
线程实现的两种方法
继承Thread类,并重写run函数
实现Runnable接口,并重写run函数
因为Java是单继承的,用实现Runnable接口的方法创建对象可以避免Java单继承机制带来 的局限。应尽可能使用实现Runnable接口的方式来创建线程。
Java中的集合:
1. List集合
ArrayList:
底层数据结构是数组,查询快,增删慢,查询是根据数组下标直接查询速度快,增删需要移动后边的元素和扩容,速度慢。线程不安全,效率高
LinkedList:
底层数据结构是链表,查询慢,增删快,查询需要遍历数组,速度慢,增删只需要增加或删除一个链接即可,速度快,线程不安全,效率高
Vector:
底层数据结构是数组,查询快,增删慢,线程安全,效率低
2.Set集合
Hashset:
底层数据结构是哈希表,是根据哈希算法来存取对象的,存取速度快,当Hashset中元素个数超过数组大小(默认值位0.75)时,会进行近似两倍的扩容,哈希表依赖两个方法hashcode()和equals()方法,方法的执行顺序,判断hashcode值是否相同,是:执行equals方法看其返回值,true:说明元素重复不添加,false:直接添加到集合,hashcode值不相同直接添加到集合。
LinkedHashset:
底层数据结构是链表和哈希表,由链表保证元素有序,由哈希表保证元素的唯一
Treeset
底层数据结构是红黑树(唯一,有序)由自然排序和比较器排序保证有序,根据返回值是否是0判断元素是否唯一
3.Map集合
HashMap:
HashMap是基于散列表实现的,其插入和查询的<k,v>的开销是固定的,可以通过构造器设置容量和负载因子来调整容器的性能,线程不安全,效率低
TreeSet:
基于红黑树实现,查看<k,v>时,它们会被排序,TreeMap是唯一带有subMap()方法的Map,subMap()方法可以返回一个子树。
LInkedHashMap:
类似于HashMap,但是迭代遍历它时,取得<K,V>的顺序是其插入次序,或者是最近最少使用(LRU)的次序。
4.Map取键值的两种方法
第一个,使用keySet方法,获得key的set,然后遍历set,就可以获得所有的value
第二个,使用entrySet方法,获得map中的所有键值对的一个视图,遍历就可获得所有的key、value
IO分类:
字符流包括 Reader、Writer;字节流包括 InputStream、OutputStream。
什么是线程安全?Vector是一个线程安全类吗?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代 码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量 的值也和预期 的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线 程使用的情况下也不会出现计算失误。很显然你可以将集合类分 成两组,线程安全和 非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不 是线程安全的。
什么是线程?
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际 运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对 运算密集型任 务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务 只需10毫秒。Java在语言层面对多线程提供了卓越的支 持,它也是一个很好的卖点。
线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的 进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞 混,每个线程都拥有单独的栈内存用来存储本地数据。
如何在Java中实现线程?
在语言层面有两种方式。java.lang.Thread 类的实例就是一个线程但是它需要调用 java.lang.Runnable接口来执行,由于线程类本身就是调用的Runnable接口所以 你可以继承 java.lang.Thread 类或者直接调用Runnable接口来重写run()方法实 现线程。
用Runnable还是Thread?
这个问题是上题的后续,大家都知道我们可以通过继承Thread类或者调用Runnable 接 口来实现线程,问题是,那个方法更好呢?什么情况下使 用它?这个问题很容易回 答,如果你知道Java不支持类的多重继承,但允许你调用多个接口。所以如果你要继 承其他类,当然是调用Runnable接口好 了。
Thread 类中的start() 和 run() 方法有什么区别?
这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。 start() 方法被用来启动新创建的线程,而且start()内部 调用了run()方法,这和直 接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中 调用,没有新的线程启 动,start()方法才会启动新线程。
sleep() 和 wait() 有什么区别
sleep()方法是Thread类的静态方法,是线程用来控制自身流程的。而wait()方法是 Object 类的方法,用于线程间的通信。
调用wait()的时候方法会释放当前持有的锁,而sleep方法不会释放锁。
sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
死锁的四个必要条件:
互斥条件:一个资源每次只能被一个进程使用
请求和保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺
环路等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
线程和进程的区别?
进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。
进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。
线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。
三次握手:
第一次连接开始:客户端发出连接请求,发出请求报文(SYN:握手信号=1,ACK:确认机制=0,SEQ:连接序列=随机数X),
客户端状态:SYN-SENT(同步已发送)
第二次:同意连接,发送同意报文(SYN:握手信号=1,ACK:确认机制=1,ack:确认信号=X+1,SEQ:连接序号=随机数Y),这里有重新产生一个序列号Y,服务器状态:SYN-RCVD(同步已收到)
第三次:客户端收到服务器的连接确认后,必须返回确认连接信号给服务器(ACK:确认机制=1, ack:确认信号=Y+1, SEQ:连接序号=随机数X+1(在上一条请求信号的基础上加1))
客户端状态:ESTAB-LISHED(连接已建立)。当服务器收到之后,服务器状态:ESTAB-LISHED(连接已建立)
四次放手:
第一次:客户端首先发送连接释放报文段(FIN:终止连接标志=1,seq:序号=X),FIN=1向服务器提出分手。客户端状态:FIN-WAIT-1(终止连接等待状态1)
第二次:因TCP的连接是全双工的双向连接,关闭也是要从两边关闭;当服务器收到客户端发来的FIN=1的标志位后,服务器不会立刻向客户端发送FIND=1的请求关闭信息,而是先向客户端发送一个ACK=1的应答信息,表示:你请求关闭的请求我已经收到,但我可能还有数据没有完成传送,你再等下,等我数据传输完成了我就告诉你;确认报文(ACK:确认机制=1,ack:确认信号=X+1,seq:序号=Y)
服务器状态:CLOSE-WAIT(关闭等待),这样客户端到服务器端的连接就释放了
客户端状态:FIN-WAIT-2(终止连接等待状态2)
第三次:服务器端数据传输完成,没有动洗传输了,服务器这边提出释放连接要求(FIN:终止连接标志=1,ACK:确认机制=1,seq:序号=Z,ack:确认信号=X+1)
服务器状态:LAST-ACK(最后确认)
第四次:host1收到FIN=1后,host1还是怕由于网络不稳定的原因,怕host2不知道他要断开连接,于是向host2发送ACK=1确认信息进行确认,把自己设置成TIME_WAIT状态并启动定时器,如果host2没有收到ACK,host2端TCP的定时器到达后,会要求host1重新发送ACK,当host2收到ACK后,host2就断开连接;当host1等待2MLS(2倍报文最大生存时间)后,没有收到host2的重传请求后,他就知道host2已收到了ACK,所以host1此时才关闭自己的连接。
Cookie跟Session的区别
1、存储位置不同
cookie的数据信息存放在客户端浏览器上。
session的数据信息存放在服务器上。
2、存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。
对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
3、存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。
session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
4、隐私策略不同
cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。
session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
5、有效期上不同
开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。
6、服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
7、浏览器支持不同
假如客户端浏览器不支持cookie:
cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
假如客户端支持cookie:
cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
session只能在本窗口以及子窗口内有效。
8、跨域支持上不同
cookie支持跨域名访问。
session不支持跨域名访问。
字节流跟字符流的区别:
字节流与字符流主要的区别是他们的的处理方式
字节流是最基本的,采用ASCII编码,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的
但实际中很多的数据是文本,又提出了字符流的概念,采用Unicode编码.它是按虚拟机的encode来处理,也就是要进行字符集的转化
这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联
为什么浮点型可能会丢失精度?
浮点十进制值通常没有完全相同的二进制表示形式。
这是 CPU 所采用的浮点数据表示形式的副作用。
为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外的结果。
导致此行为的原因是下面之一:
十进制数的二进制表示形式可能不精确。
使用的数字之间类型不匹配(例如,混合使用浮点型和双精度型)。
为解决此行为,大多数程序员或是确保值比需要的大或者小,或是获取并使用可以维护精度的二进制编码的十进制 (BCD) 库。
浮点值的二进制表示形式影响浮点计算的精度和准确性。
什么是maven?
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周 期 (Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段 (phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。
此外,Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等