Java基础
1. JDK和JRE有什么区别?
- JVM: java虚拟机,负责把.class 二进制文件翻译成不同系统上的机器操作指令
- JRE: 包含了JVM和一些类库,如果不对代码进行编译只是运行,那么只需要jre就可以了
- JDK: 包含了JRE和一些开发工具,如javac命令可以对java代码进行编译
2. ==和equals的区别是什么?
- 凡是比较基本类型都只能用==,比较的结果就是眼睛能看到的字面量,基本类型只有8种,byte,short,int,long,char,float,double,记住String不是基本类型。基本类型不是对象,所以不存在使用equals比较。
- 凡是比较引用类型(对象)的时候==和equals的使用是有区别的。==的使用是比较两个引用(对象)是不是指向同一个内存地址,equals比较的是字面量是不是一致。
- 基本类型的包装类是对象类型,所以除非两个相同字面量的引用指向同一个内存地址,值才会相等。
3. 两个对象的hashCode()相同,则equals()也一定为true,对吗?
结论:
- 两个对象equals相等,则它们的hashcode必须相等,反之则不一定。
- 两个对象==相等,则其hashcode一定相等,反之不一定成立。
hashCode 的常规协定:
1)在 Java 应用程序执行期间,在对同一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行equals比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2)两个对象的equals()相等,那么对这两个对象中的每个对象调用 hashCode方法都必须生成相同的整数结果。
3)两个对象的equals()不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。但是,为不相等的对象生成不同整数结果可以提高哈希表的性能。
4. final在Java中有什么作用?
final作为Java中的关键字可以用于三个地方。用于修饰类、类属性和类方法。 特征:凡是引用final关键字的地方皆不可修改!
-
修饰类:表示该类不能被继承;
-
修饰方法:表示方法不能被重写;
-
修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
相信大家都具备基本的常识: 被final修饰的变量是不能够被改变的. 但是这里的"不能够被改变"对于不同的数据类型是有不同的含义的.
当final修饰的是一个基本数据类型数据时, 这个数据的值在初始化后将不能被改变; 当final修饰的是一个引用类型数据时, 也就是修饰一个对象时, 引用在初始化后将永远指向一个内存地址, 不可修改. 但是该内存地址中保存的对象信息, 是可以进行修改的.
5. Java中的Math.round(-1.5)等于多少?
| d | Math.round(d) | Math.ceil(d) | Math.floor(d) |
|---|---|---|---|
| 1.3 | 1 | 2.0 | 1.0 |
| 1.5 | 2 | 2.0 | 1.0 |
| 1.7 | 2 | 2.0 | 1.0 |
| -1.3 | -1 | -1.0 | -2.0 |
| -1.5 | -1 | -1.0 | -2.0 |
| -1.7 | -2 | -1.0 | -2.0 |
Math.round(d): 四舍五入,入的时候是到大于它的整数Math.ceil(d): 返沪不小于的最小整数Math.floor(d): 返回不大于的最大整数
6. String属于基础的数据类型吗?
String不属于八种基本类型,它是引用类型。
-
String str = "kvill"和String str = new String("kvill")的区别常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
Java会确保一个字符串常量只有一个拷贝,用
new String()创建的字符串不是常量,不能再编译器就确定下来,所以new String()创建的字符串不放在常量池中,它们会被放在堆上,有自己的内存地址。 -
String.intern()存在于.class文件中的常量池,在运行期被JVM转载,并且可以扩充,String的
intern()方法就是扩充常量池的一个方法,当一个String实例str调用intern()方式时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其引用,如果没有,则在常量池中新增一个Unicode等于str的字符串并返回它的引用。 -
关于
equals()和==区别equals()对于String简单的来说就是比较两个字符串的Unicode序列是否相同,如果相等则返回true;而==是比较两字符串的地址是否相同,比较是不是同一个字符串的引用 -
关于String是不可变的
7. Java中操作字符串都有哪些类?它们之间有什么区别?
String,StringBuffer,StringBuilder
-
StringBuffer,StringBuilder都是字符串的缓冲区、可变的字符序列,具有相同的构造方法
-
内存,String是不可变的对象,每次操作都会生成新的String对象,然后指针指向新的String对象;StringBuffer、StringBuilder可以在原有的对象基础上进行操作,所以在经常改变字符串内容的情况下,最好不要用String
-
出现版本,StringBuffer是Jdk1.1, StringBuilder是Jdk1.5
-
线程安全, StringBuffer是线程安全的,同步锁(synchronized),多线程仍可以保证数据安全,StringBuilder线程不安全,多线程不能保证数据安全
-
效率, StringBuilder > StringBuffer > String
-
总结,不频繁增改字符,就用String, 否则用StringBuffer或StringBuilder
8. String str="i"与 String str=new String(“i”)一样吗?
9. 如何将字符串反转?
-
利用StringBuffer或者StringBuilder的reverse成员方法
-
利用String的toCharArray方法先将字符串转化为char类型数组,然后将各个字符进行重新拼接
-
利用String的CharAt方法去除字符串进行拼接
10. String类的常用方法都有哪些?
indexOf()返回指定字符得索引charAt()返回指定索引处得字符repalce()字符串替换trim()去除字符串两端的空白split()分割字符串 返回分割后的字符串数组getBytes()返回字符串的byte类型数组length()返回字符串的长度toLowerCase()字符串转小写toUpperCase()字符串转大写substring()截取字符串equals()字符串比较
抽象类和接口
抽象类
- abstract修饰的类为抽象类,此类不能被实例化
- abstract修饰的方法为抽象方法,此方法不能有方法体
- 抽象类不能有对象
- 有抽象方法的类一定是抽象类,但是抽象类不一定有抽象方法
- 抽象类中的抽象方法必须在子类中被重写
子类实现方法必须含有相同的或者更低的访问级别(public > protected > private)。抽象类的子类为父类中所有抽象方法的具体实现,否则也为抽象类。
为什么要有抽象类?有些东西不一定能是一个人写的,所有有些方法当时可能写不出来,所以写个大概。
抽象方法不饿能有方法题,在方法后面加一个大括号而里面什么也不写也不行,否则编译器会报
abstract methods do not specify a body
当一个类继承抽象类时候,这个类必须去重写所有继承的抽象类的抽象方法,否则编译器会报
The type Cat must implement the inherited abstract method Animal.eat()
接口
- 接口中所有的属性默认为:
public static final *** - 接口中所有的方法默认为:
public abstract *** - 接口不再像类一样用关键字
extends去继承,而是使用implements去实现,也就是说类和接口的关系是实现 - 一个类可以实现多个接口,但只能继承一个类,所以可以通过这种方式是实现多继承
*抽象类和接口的区别
- 抽象类描述的是"是不是"的问题,而接口描述的是"有没有"的问题;接口强调特定功能的实现,而抽象类强调所属关系
- 接口只有定义,不能有方法的实现,而抽象类可以既有定义又有实现,方法可以在抽象类中实现
- 实现接口的关键字为
implements,继承抽象类的关键字为extends,一个类可以实现多个接口,但一个类只能继承一个抽象类,所以使用接口可以间接实现多继承 - 接口的成员变量默认为
public static final,必须赋初值,不能被修改;所有的成员方法public abstract。抽象类中成员变量默认default,可以在子类中被重新定义,也可以被重新赋值;抽象方法被abstract修饰,不能被private static synchronized native等修饰,必须以分号结尾,不带花括号 - 接口被用于常用的功能,便于以后委会和添加删除,而抽象类更倾向于充当公共角色,不适用于日后重新对里面代码进行修改,功能需要累积时用抽象类,不需要累积时使用接口
11. 抽象类必须要有抽象方法吗?
12. 普通类和抽象类有哪些区别?
13. 抽象类能使用 final 修饰吗?
14. 接口和抽象类有什么区别?
15. Java中IO流分为几种?
- 按照流的流向分,可以分为输入流和输出流;
- 按照操作单元划分,可以划分为字节流和字符流;
- 按照流的角色划分为节点流和处理流。
Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java IO流的40多个类都是从如下4个抽象类基类中派生出来的。
- InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
- OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
按操作方式分类结构图:
按操作对象分类结构图:
16. BIO、NIO、AIO有什么区别?
- BIO(Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的I/O并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的BIO模型是无能为力的。因此,我们需要一种更高效的I/O处理模型来应对更高的并发量。
- NIO(New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4中引入了NIO框架,对应java.nio包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的Socket和 ServerSocket相对应的SocketChannel 和ServerSocketChannel两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用NIO的非阻塞模式来开发
- AIO(Asynchronous I/O):AIO也就是NIO 2。在Java 7中引入了NIO的改进版NIO 2,它是异步非阻塞的IO模型。异步IO是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO是异步IO的缩写,虽然NIO在网络操作中,提供了非阻塞的方法,但是NIO的IO行为还是同步的。对于NIO来说,我们的业务线程是在IO操作准备好时,得到通知,接着就由这个线程自行进行IO操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说AIO的应用还不是很广泛,Netty之前也尝试使用过AIO,不过又放弃了。
17. Files的常用方法都有哪些?
-
Files.exists():检测文件路径是否存在。 -
Files.createFile():创建文件。 -
Files.createDirectory():创建文件夹。 -
Files.delete():删除一个文件或目录。 -
Files.copy():复制文件。 -
Files.move():移动文件。 -
Files.size():查看文件个数。 -
Files.read():读取文件。 -
Files.write():写入文件。