现在新技术迭代非常快,我们一方面要学习掌握更多的新技术,同时我们需要不断的巩固已学的知识,一点点的知识积累终会变成质的飞跃。现在我就想来总结一下java一些常用的面试题。
参考文章:
原文:1)https://blog.csdn.net/sufu1065/article/details/88051083
2)https://cyc2018.github.io/CS-Notes/#/notes/Java%20%E5%9F%BA%E7%A1%80
一.java基础
1.JDK和JRE有什么区别?
答: JDK : JDK是Java Development Kit的缩写,JDK 是java的开发工具包,主要面向开发人员,JDK包含JRE,安装JDK的同 时会安装JRE。
JRE: JRE是Java Runtime Environment的缩写,是java程序运行环境,主要面向java程序使用者,JRE是可以在其上运行、测试和传输应用程序的Java平台。它包括Java虚拟机(jvm)、Java核心类库和支持文件。它不包含开发工 具 (JDK)–编译器、调试器和其它工具。
JVM: JVM是java的虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。
详细解释:https://blog.csdn.net/chen_006/article/details/88656268
2.== 和equals()有什么区别?
答: == : 1.如果用来判断基本数据类型(也称原始数据类型)(byte,short,char,int,long,float,double,boolean)。他们之间的比较,应用双等号(==),比较的是他们的值。
2.如果用来判断引用数据类型,当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。
equals() : 如果用来判断引用类类型,默认情况下比较的是地址值,也可以用来字符串是否相等,我们可以根据情况自己重写该方法。一般重写都是自动生成,比较对象的成员变量值是否相同。
详细解释:https://www.cnblogs.com/qianguyihao/p/3929585.html
https://www.cnblogs.com/zhxhdean/archive/2011/03/26/1996468.html
3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
答:不对,两个对象的 hashCode()相同,equals()不一定 true。
详细举例解释:https://blog.csdn.net/qq_35771266/article/details/91345052
4.final 在 Java 中有什么作用?
答:final关键字的用法,可以修饰类,变量,方法,表示变量不可修改,类不可以继承,方法不可覆盖。
修饰类: 当一个类被final修饰的时候,表示该类为最终类,不可被继承,比如常用的String类就是最终类。
修饰方法:当一个方法被final修饰的时候,表示该方法为最终方法,这个方法不可被子类重写,但是可被子类继承。
修饰变量: 如果该变量是基本数据类型,说明该变量为一个常量,值不可修改。 如果变量为引用数据类型,比如对象、数 组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
详细解释:https://www.cnblogs.com/chhyan-dream/p/10685878.html
https://www.cnblogs.com/tanshaoshenghao/p/10908771.html
5.Java 中的 Math.round(-1.5) 等于多少?
答: Math.round(-1.5)的返回值是-1。四舍五入的原理是在参数上加0.5然后做向下取整
6.String 属于基础的数据类型吗?
答:不属于。这里只要考察Java的基本数据类型有哪些。
Java 8种基本数据类型都有: byte char int double short long boolean float
类型 | 占用字节 | 占用位数 |
---|---|---|
byte | 1 | 8 |
char | 2 | 16 |
int | 4 | 32 |
double | 8 | 64 |
short | 2 | 16 |
long | 8 | 64 |
boolean | 1 | 1 |
float | 4 | 32 |
7.java 中操作字符串都有哪些类?它们之间有什么区别?
答:Java操作字符串的类我知道的有三个,String StringBuffer StringBuilder。这三种都是通过char[]保存的字符串,
String :String修饰的是不可变的字符串,对String修饰的变量修改时相当于重新创建一个对象。
StringBuffer: 常用来操作一个可变的字符串,拼接字符串的方法是append(), StringBuffer中的方法大多是用synchronized 关键字修饰,因而是线程安全的,更加适用于多线程的情况下。
StringBuilder: 常用来操作一个可变的字符串,拼接字符串的方法是append(),StringBuffer中的方法没有用synchronized修 饰,因为是线程不安全的,效率更高,更加适用于单线程的情况下。
8.String str="i"与 String str=new String(“i”)一样吗?
答: 不一样。
String str="i" :是指将i在内存的地址指向str这个变量,如果此时有一个变量str2 的值为i 此时str 和str2共用的是一块内 存。
String str=new String("i") : 则是将new String("i");的对象地址赋给str2,需要注意的是这句话是新创建了一个对象。如果此 时 String str4= new String("i");那么相当于又创建了一个新的对象,然后将对象的地址值赋给str4,虽然str2的 值和str4的值是相同的,但是他们依然不是同一个对象了。
9.如何将字符串反转?
答: 可以使用StringBuffer StringBuilder 的reverse方法,还可以自己实现。
详细解释: 举个例子,https://blog.csdn.net/meism5/article/details/89329699
10.String 类的常用方法都有那些?
答: equals() spilt() indexOf () charAt() length() replace() trim() getBytes() toLowerCase() toUpperCase() substring()
- equals() 主要用来判断俩个字符串是否相等
- spilt() 主要是对字符串进行切割,返回字符串数组
- indexOf 主要是用来返回指定字符串的索引
- charAt() 根据指定字符得索引
- length() 主要是返回字符串的长度
- replace() 主要是用来字符串的替换
- trim() 去除字符串俩端的空白
- getBytes() 返回字符串的byte类型数组
- toLowerCase() 字符串转小写
- toUpperCase 字符串转大写
- substring 切割字符串
11.抽象类必须要有抽象方法吗?
答:不必须。
通常情况下我们使用abstract去修饰一个抽象类。
抽象类的总结:
-
1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
-
2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。(抽象类和抽象方法都用abstract修饰)
-
3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
-
4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
-
5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
抽象类需要注意的点:
- 1.如果一个类包含抽象方法,那么该类必须是抽象类。
- 2.任何子类必须重写父类的抽象方法,或者声明自身为抽象类
- 3.抽象类中可以不定义抽象方法,抽象方法目的仅仅为了不让该类创建对象。
- 4.抽象关键字abstract与 final , private , static 这三个关键字不共存。
抽象类的用法:
AbstractClassExample
package com.bos.test;
/**
* @Author tanghh
* @Date 2020/7/9 11:10
*/
public abstract class AbstractClassExample {
protected int x;
private int y;
public abstract void func1();
public void func2() {
System.out.println("func2");
}
}
AbstractExtendClassExample
package com.bos.test;
/**
* @Author tanghh
* @Date 2020/7/9 11:15
*/
public class AbstractExtendClassExample extends AbstractClassExample {
@Override
public void func1() {
System.out.println("func1");
}
}
MenuTest
package com.bos.test;
public class MenuTest {
public static void main(String[]args){
//报错
// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated
//可以引用
AbstractClassExample ac2 = new AbstractExtendClassExample();
ac2.func1();
}
}
12.普通类和抽象类有哪些区别?
答:
- 抽象类不能被实例化
- 抽象类可以有抽象方法,抽象方法只需申明,无需实现
- 含有抽象方法的类必须申明为抽象类
- 抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类
- 抽象方法不能被声明为静态
- 抽象方法不能用private修饰
- 抽象方法不能用final修饰
13.抽象类能使用 final 修饰吗?
答:不能。
抽象类可被继承,而被final修饰的话,说明该类不可修改,不可继承。 这里的话读者还可自行去看一下final关键字的用法。
14.接口和抽象类有什么区别?
深入理解抽象类和接口的区别:https://www.ibm.com/developerworks/cn/java/l-javainterface-abstract/
抽象类和接口的区别:
接口:1.接口使用interface修饰 2.接口不能实例化 3.Java 支持单继承,即只能继承一个类,但是可以实现多个接口。
4.接口中方法是抽象方法,不能实现
抽象类:1. 抽象类使用abstract修饰 2.抽象类中包含抽象方法和非抽象方法 3.抽象类不可以实例化。 4. 有抽象方法的类 一 定是抽象类,抽象方法中没有具体实现。 5.如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类 可以不必是抽象类,否则就是抽象类。
接口的用法:
需要注意点:
1. 接口中的字段 ,方法 默认都是public 的 ,并且不允许定义为private 或者protected.
2. 接口中的字段默认都是static 和final的。
3. 在以往 ,接口新增一个方法,那么所8开始,接口有实现了改接口的类都要修改,从java可以拥有默认方法的实现。
package com.bos.test;
/**
* @Author tanghh
* @Date 2020/7/9 11:24
*/
public interface InterfaceExample {
void func1();
default void func2(){
System.out.println("func2");
}
int x = 123;
//报错【】【】Variable 'y' might not have been initialized
// int y;
public int z = 0; // Modifier 'public' is redundant for interface fields
// private int k = 0; // Modifier 'private' not allowed here
// protected int l = 0; // Modifier 'protected' not allowed here
// private void fun3(); // Modifier 'private' not allowed here
}
15.java 中 IO 流分为几种?
答:根据流的流向分为输入流和输出流。 根据操作单元可以划分为字节流和字符流。根据流的角色可以分为节点流和处理流。
- InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
- OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
按照操作方式可以分为:
详细解释:https://blog.csdn.net/weixin_43643277/article/details/96282707
16.BIO、NIO、AIO 有什么区别?
答:IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
BIO: 在jdk1.4出现之前,我们建立网络连接一般使用BIO,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket 来对服务端进行通信。我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程。BIO是一个连接一个线程。
BIO适用于适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前 的唯一选择,但程序直观简单易理解。
NIO: NIO本身是基于事件驱动思想来完成的,其主要想解决的是BIO的大并发问题。NIO则是使用单线程或者只使用少量 的多线程,每个连接共用一个线程。NIO是一个请求一个线程。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂, JDK1.4开始支持
AIO : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去 启动线程进行处理,
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复 杂,JDK7开始支持。
详细地址: https://blog.csdn.net/skiof007/article/details/52873421
17.Files的常用方法都有哪些?
- Files.exists() 检测文件路径是否存在
- Files.createFile()创建文件
- Files.createDirectory()创建文件夹
- Files.delete() 删除文件或者目录
- Files.copy() 复制文件
- Files.move() 移动文件
- Files.size()查看文件个数
- Files.read() 读取文件
- Files.write()写入文件
18.基本类型和 包装类型之间的赋值使用自动装箱和拆箱
Integer x = 2; // 装箱 调用了 Integer.valueOf(2)
int y = x; // 拆箱 调用了 X.intValue()
19.参数传递 包含值传递 和引用传递
20.类加载顺序
存在继承的情况下,类初始化顺序为:
21.Object通用方法
equals()
toString 方法
22. switch
从java7开始,可以在switch条件判断语句中使用String 对象,switch不支持long,是因为switch的设计初衷是对那些只有少数几个值进行等值判断。
package com.bos.test;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bos.common.file.FileThreadResource;
import org.junit.Test;
import java.io.*;
import java.text.ParseException;
import java.util.List;
public class MenuTest {
public static void main(String[]args){
String str = "one";
switch(str){
case "one":
System.out.println("one");
break;
case "two":
System.out.println("two");
break;
}
}
}
23.static的用法
静态变量的用法:
package com.bos.test;
public class MenuTest {
/**
* 实例变量
*/
private int aa;
/**
* 静态变量
*
* @param args
*/
private static int bb;
public static void main(String[] args) {
//获取实例变量 (实例变量需要先创建类实例,它与改实例共存)
MenuTest menuTest = new MenuTest();
int aa = menuTest.aa;
//获取静态变量(类变量 可以通过类名访问 ,静态变量在内存中只存一份)
int bb = MenuTest.bb;
}
}
静态方法 ,静态变量 静态内部类的用法:(全部代码)
package com.bos.test;
public class MenuTest {
/**
* 实例变量
*/
private int aa;
/**
* 静态变量
*
* @param args
*/
private static int bb;
/**
* 静态语句块(在类初始化的时候运行一次(MenuTest test = new MenuTest()))
*/
static{
System.out.println("1234");
}
/**
* 静态方法
*/
public static void send() {
//报错,无法引用
// int aa1 = aa;
//可以引用
int bb1 = bb;
//不可以引用(静态方法中不能有this 和super关键字,因此这俩个关键字只能与具体对象相关联)
// int bb2 = this.aa;
}
/**
* 内部类
*/
class InnerClass{
}
/**
* 静态内部类
* @param args
*/
static class StaticInnerClass{
}
public static void main(String[] args) {
//获取实例变量 (实例变量需要先创建类实例,它与改实例共存)
MenuTest menuTest = new MenuTest();
int aa = menuTest.aa;
//获取静态变量(类变量 可以通过类名访问 ,静态变量在内存中只存一份)
int bb = MenuTest.bb;
//访问内部类
MenuTest test = new MenuTest();
InnerClass innerClass = test.new InnerClass();
//访问静态内部类
StaticInnerClass staticInnerClass = new StaticInnerClass();
}
}
24. 访问权限修饰符(private protected public)
java中有三个访问权限修饰符:public protected 以及public ,如果不加访问修饰符,表示包级可见。
访问权限 | 类 | 包 | 子类 | 其他包 |
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
private | √ | × | × | × |
default | √ | √ | × | × |
需要注意的点:
1. 我们可以对类或勒种的成员(字段和方法) 加上访问修饰符
类可见 表示其他类可以用这个类创建实例对象,成员可见表示其他类可以用这个类的实例对象访问到该成员。
25.super关键字的用法
super 是一个指代变量,用于在子类中指代父类对象。
a.访问父类的构造函数
b.访问父类的成员
子类一定会调用父类的构造函数来完成初始化工作,一般是调用父类的默认构造函数,如果子类需要调用父类其他构造函数,那么就可以使用super() 函数。
SuperExample
package com.bos.test;
/**
* @Author tanghh
* @Date 2020/7/9 11:39
*/
public class SuperExample {
protected int x;
protected int y;
public SuperExample(int x, int y) {
this.x = x;
this.y = y;
}
public void func() {
System.out.println("SuperExample.func()");
}
}
SuperExtendExample
package com.bos.test;
/**
* @Author tanghh
* @Date 2020/7/9 11:40
*/
public class SuperExtendExample extends SuperExample {
private int z;
public SuperExtendExample(int x, int y, int z) {
super(x, y);
this.z = z;
}
@Override
public void func() {
super.func();
System.out.println("SuperExtendExample.func()");
}
}
MenuTest
package com.bos.test;
public class MenuTest {
public static void main(String[]args){
SuperExample e = new SuperExtendExample(1, 2, 3);
e.func();
}
}
26.重载和重写
重写:存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。
重写有三个限制:
1.子类方法的访问权限必须大于等于父类方法
2.子类方法的返回类型必须是父类方法返回类型或为其子类型。
3.子类必须是父类抛出异常类型或为其子类型。
重写的例子:
class SuperClass {
protected List<Integer> func() throws Throwable {
return new ArrayList<>();
}
}
class SubClass extends SuperClass {
@Override
public ArrayList<Integer> func() throws Exception {
return new ArrayList<>();
}
}
重载: 存在于同一个类中,指一个方法与已经存在的名称方法上相同,但是参数类型,个数 ,顺序至少有一个不同。
需要注意的是:返回值不同,其他都相同的不算重载。
27. throw 和throws的区别
throw
1.表示方法内抛出某种异常对象,
2.如果异常对象是非RuntimeException 则需要在方法申明时加上该异常的抛出,则需要加上throws语句,或者在方法体内try catch
3.执行到throw语句则后面的语句不再执行。
throws
1.方法的定义上使用throws表示这个方法可以抛出某种异常
2.需要由方法的调用者进行异常处理。
后面慢慢补充。。