文章目录
1、JDK和JRE有什么区别
- jre:包括java虚拟机和java核心类库,java运行时环境
- jdk:包括java开发工具和jre
- 使用jdk开发的程序,交给jre运行
- jdk是JAVA程序开发时用的开发工具包,其内部也有JRE运行环境。JRE是JAVA程序运行时需要的运行环境
2、面向对象和面向过程的区别?
概念:
-
面向过程是具体化的,流程化的,解决一个问题,你需要一步一步的分析,一步一步的实现。
-
面向对象是模型化的,将一切事物看成一个对象,你只需抽象出一个类,这是一个封闭的盒子,在这里你拥有数据也拥有解决问题的方法。需要什么功能直接使用就可以了,不必去一步一步的实现,至于这个功能是如何实现的,管我们什么事?我们会用就可以了。
-
面向对象的底层其实还是面向过程,把面向过程抽象成类,然后封装,方便我们使用的就是面向对象了。
面向过程:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象:
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
缺点:性能比面向过程低
3、Java中equals和 ==之间的区别(重点)
equals 和 == 最大的区别是一个是方法一个是运算符
- ==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等。
- equals():用来比较方法两个对象的内容是否相等。
注意
equals 方法不能用于基本数据类型的变量,如果没有对 equals 方法进行重写,则比较的是引用类型的变量所指向的对象的地址
4、hashCode和equals方法的关系
equals相等,hashcode必相等;hashcode相等,equals可能不相等。
hashCode()返回该对象的哈希码值;equals()返回两个对象是否相等
5、构造器Constructor是否可被override
构造器不能被重写,不能用static修饰构造器,只能用public、private、protected
三个权限修饰符,且不能有返回语句
6、访问控制符public,protected,private,以及默认的区别
- private只有在本类中才能访问
- public在任何地方都能访问
- protected在同包内的类及包外的子类能访问
- 默认不写在同包内能访问
7、是否可以继承String类?
String类是final类故不可以继承,一切由final修饰过的都不能继承
8、JDK8的新特性
- 引入了lambda表达式,可以简化匿名内部类的代码,允许将方法作为参数,lambda表达式的关键是函数式接口。
- 函数式接口:就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口
- 可以在接口中使用default定义默认方法和静态方法,引入默认方法方便了接口升级的维护,之前如果在接口中新增一个方法必须修改所有实现类
- 引入了stream流,支持链式编程,为集合类和数组提供了一些方便的操作方法,例如:filter,skip,limit,map,concat等
- 允许重复使用注解,扩大了注解的使用范围,可以用在局部变量和泛型,方法异常上
- 引入了Optional类解决空指针异常,更新了日期类的API( LocalDate | LocalTime | LocalDateTime)等
- 方法引用和构造器调用
9、什么是方法重载
在一个类中,方法名相同,但是参数列表不同(参数个数,类型,顺序),和 方法返回值类型无关
10、什么是方法重写
- 方法名相同
- 参数也相同
- 子类重写之后的权限修饰符不能更低
- 子类重写之后抛出异常不能更大
11、什么是面向对象,三大特征
面向对象的方法主要是把事物给对象化,包括其属性和行为。
-
封装:
封装就是把属于同一类事物的共性(包括属性与方法)归到一个类中,以方便使用 -
继承(extends关键字):
子类继承父类之后,子类就拥有了父类中非私有的属性和方法,构造方法不能继承特点: 单继承 一个子类只能继承一个父类,但可以实现多重继承
-
多态:多态性是指允许不同子类型的对象对同一消息作出不同的响应
父类的引用指向子类的对象 eg: Person person = new Student
instanceof关键字用来判断类型是否相同 如果匹配,可以进行类型之间的转换
12、构造方法
默认会有一个无参构造,如果写了构造,就不再提供无参构造,必须手动添加无参构造
- 构造方法也是可以重载的,方法名相同,参数列表不同。
- 构造方法之间也是可以互相调用的this(参数);
- 构造方法的调用只能放在第一行
13、抽象类abstract
- 用来修饰类和方法,不能用来修饰属性和构造方法。使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要子类被重写。
- 形式:abstract返回值类型 方法名(参数); 没有方法体
特点:
- 不能被例化
- 必须有子类
- 有构造方法,给子类用的,子类初始化之前先初始化父类
- 可以有抽象方法,也可以没有抽象方法
- 抽象类不能被final修饰
- 抽象方法不能有方法体,即没有{}
14、接口interface
特点:
- 不能实例化
- 必须有实现类
- 没有构造方法
- 可以多实现
作用:相当于规则,标准,不同的实现类去实现。用户调用的时候,不关心具体的实现,只需要关注接口的具体功能。
15、final,finally,finalize区别
- final
- 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承
- 将变量或方法声明为final,可以保证他们在使用中不被改变
- 被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改
final作为Java中的关键字可以用于三个地方。用于修饰类、类属性和类方法
特征:凡是引用final关键字的地方皆不可修改!
-
修饰类:表示该类不能被继承
-
修饰方法:表示方法不能被重写
-
修饰变量:表示变量只能一次赋值,以后值不能被修改(常量)
- 修饰的是基本数据类型数据时:值在初始化后不能改变
- 修饰的是引用数据类型时也就是修饰一个对象时:引用在初始化后将永远指向一个内存地址,不可修改,但是该内存中保存的对象信息,是可以进行修改的
- 常量:所有的字母都大写,如果有多个单词,中间用下划线 “ _ ”连接
注意:
final修饰基本类型变量,其值不能改变,由原来的变量变为常量;但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变
-
finally
- 在处理异常时,提供finally块来执行任何清除工作
- 如果有finally的话,则不管是否发生异常,finally语句都会被执行
-
finalize
- 方法名, 使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作
- finalize() 方法是在垃圾收集器删除对象之前被调用的
- 它是在 Object 类中定义的,因此所有的类都继承了它
16、Java的数据类型
基本数据类型
- 整数型 byte,short,int,long
- 浮点型 float,double
- 布尔型 boolean
- 字符型 char
引用数据类型
- 类 class
- 接口 interface
- 数组 array
17、抽象类和接口的区别?
使用方式:
- 抽象类只能通过继承被使用
- 接口必须通过实现被使用
实现方法:
- 抽象类不仅可以提供抽象方法,也可以提供实现方法
- 接口只能提供抽象方法,不能提供实现方法。在Java8版本开始,接口可以提供实现方法了,
前提
是要在方法前面加一个default
修饰符
18、java中的Math.round(-1.5)等于多少?
Math的round方法是四舍五入,如果参数时负数时,则往大的数变,所以
- Math.round(-1.5) = -1
- Math.round(1.5) = 2
19、String属于基础的数据类型吗?
不属于
Java8中基础数据类型有byte,short,char,int,long,float,double,boolean
20、Java中操作字符串都有哪些类,他们之间有什么区别?
java中提供了两种类型的字符串:String和StringBuffer/StringBuilder,他们都可以存储和操作字符串
区别:
- String是只读字符串,也就意味着String引用的字符串内容是不能被改变的
- StringBuffer/StringBuilder表示的字符串对象可以直接进行修改
- StringBuilder是java5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为他的方法都没有被synchronized修饰,因此他的效率理论上也比StringBuffer高
21、String str = "i"与String str = new String(“i”)的区别?
- String str = “i”; 在编译期,JVM会去常量池来查找是否存在“i”,如果i不存在,就会在常量池中开辟一个空间来存储i;如果i存在,那么就不需要开辟新空间,只需在栈中开辟一个名字为str的空间,来存储i在常量池中的地址值
- String str = new String(“i”);在编译阶段JVM先去常量池中查找是否存在“i”,如果i不存在,则在常量池中开辟一个空间存储“i”。在运行时期,通过String类的构造器在堆内存中new了一个空间,然后将String池中的“i”复制一份存放到该堆空间中,在栈中开辟名字为str的空间,存放堆中new出来的这个String对象的地址值
22、自动类型转换问题
基本数据类型和String类型相加结果一定是字符串型是正确的
23、this和super关键字
- this关键字
- this是对象内部指代自身的引用,同时也是解决成员变量和局部变量同名问题
- this可以调用成员变量,不能调用局部变量
- this也可以调用成员方法,在普通方法中可以省略this,在构造方法中不允许省略,必须是构造方法的第一句
- this关键字不允许在静态方法中出现
- super关键字
- super代表对当前对象的直接父类对象的引用,super可以调用直接父类的成员变量
- super可以调用直接父类的成员方法
- super可以调用直接父类的构造方法,只限构造方法中使用,且必须是第一条语句
24、 static关键字
被 static 修饰的成员称为静态成员或类成员 ,可以修饰方法和属性,随着类的加载而加载,User.java—>编译User.class–>运行的是class文件。User.class被加载到内容,Class这个类的对象,static修饰的变量这个时候就会赋值了,静态的方法也可以调用了,static修饰的属性和方法已经被初始化ok了,就可以调用,用类名调用
特点:
- static可以修饰变量,方法,代码块和内部类
- 随着类的加载而加载
- 优先于对象而存在
- 可以使用类名直接调用
- 不可以使用this来调用 方法
25、基本数据类型和包装类
八个基本数据类型的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
doule | Double |
自动装箱和自动拆箱
- 实现了包装类和基本数据类型之间的自动转换
int和integer的区别
- int默认值为0,而integer的默认值为null,即integer可以区分未赋值和值为0的区别,int无法表达出未赋值的情况
26.String类的常用方法都有哪些?
- 和长度有关的方法
返回类型 | 方法名 | 作用 |
---|---|---|
int | length() | 得到一个字符串的字符个数 |
- 和数组有关的方法
返回类型 | 方法名 | 作用 |
---|---|---|
byte[] | getByte() | 将一个字符串转换成字节数组 |
char[] | toCharArray() | 将一个字符串转换成z字符数组 |
String | spilt(String) | 将一个字符串按照指定内容进行分割 |
- 和判断有关的方法
返回类型 | 方法名 | 作用 |
---|---|---|
boolean | equals | 判断两个字符串的内容是否一样 |
boolean | contains(String) | 判断一个字符串里面是否包含指定的内容 |
boolean | startsWith(String) | 判断一个字符串是否以指定的内容开头 |
boolean | endsWith(String) | 判断一个字符串是否以指定的内容结尾 |
- 和改变内容有关的方法
返回类型 | 方法名 | 作用 |
---|---|---|
String | replace(String,String) | 将某个内容全部替换成指定内容 |
String | replaceAll(String,String) | 将某个内容全部替换成指定内容,支持正则 |
String | repalceFirst(String,String) | 将第一次出现的某个内容替换成指定的内容 |
String | substring(int) | 从指定下标开始一直截取到字符串的最后 |
String | substring(int,int) | 从下标x截取到下标y-1对应的元素 |
String | trim() | 去除一个字符串的前后空格 |
String | toUpperCase() | 将一个字符串全部转换成大写 |
String | toLowerCase() | 将一个字符串全部转换成小写 |
- 和位置有关的方法
返回类型 | 方法名 | 作用 |
---|---|---|
char | charAt(int) | 得到指定下标位置对应的字符 |
int | indexOf(String) | 得到指定内容第一次出现的下标索引 |
int | lastIndexOf(String) | 得到指定内容最后一次出现的下标 |
27、Files的常用方法都有哪些?
- Files.exists() 检测文件路径是否存在
- Files.createFile()创建文件
- Files.createDirectory()创建文件夹
- Files.delete() 删除文件或者目录
- Files.copy() 复制文件
- Files.move() 移动文件
- Files.size()查看文件个数
- Files.read() 读取文件
- Files.write()写入文件
28、&和&&的区别和联系
&和&&都可以用作逻辑运算符
区别:
- 无论任何情况,&两边的操作数或表达式都会参与运算,而&&运算时,左边操作数或表达式为false时,右边操作数或表达式将不再参与运算,此时结果都为false
- &还可以用作位运算符
29、如何用最效率的方法算出2乘以8等于多少
使用位运算符(< <)来实现 ,它是将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,位运算cpu直接支持的,效率最高。所以,2乘以8等于几的最效率的方法是2 << 3
30、Java中如何将对象序列化,什么情况下需要序列化
序列化:将 Java 对象转换成字节流的过程。
反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,需要序列化。
序列化的实现: 类实现java.io.Serializable接口
31、Java中参数传递的方式
- 按值传递(call by value:传递的是具体的值,如基础数据类型)==> 不能改变实参的数值
- 按引用传递(call by reference:传递的是对象的引用,即对象的存储地址) ==> 不能改变实参的参考地址,可以通过该地址访问地址中的内容从而实现内容的改变
32、如何将字符串反转
package com.jl.resven;
public class Test {
// 1.利用 StringBuffer或StringBuilder的reverse成员方法
public static String test1(String str){
return new StringBuffer(str).reverse().toString();
}
// 2.利用 String 的 toCharArray 方法先将字符串转化为 char 类型数组
// 然后将各个字符进行重新拼接
public static String test2(String str){
char[] chars = str.toCharArray();
String str1 = "";
for (int i = chars.length - 1; i >= 0; i--){
str1 += chars[i];
}
return str1;
}
// 3.利用String的CharAt方法取出字符串中的各个字符
public static String test3(String str){
String str2 = "";
int length = str2.length();
for (int i = 0; i < length; i++) {
str2 = str.charAt(i) + str2;
}
return str2;
}
public static void main(String[] args) {
String str = "123abc";
System.out.println("变换前:" + str);
System.out.println("----------------------");
System.out.println("变换后:" + test1(str));
System.out.println("变换后:" + test2(str));
System.out.println("变换后:" + test2(str));
}
}
33、使用递归计算n!
public class Test1 {
public int test(int n){
if (n ==1 || n == 0){
return n;
}else {
return n*test(n-1);
}
}
public static void main(String[] args) {
Test1 test1 = new Test1();
System.out.println(test1.test(3));
}
}
- 递归算法是一种直接或者间接地调用自身算法的过程
- 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口
34、请写出冒泡排序代码
public class Test2 {
public static void main(String args[]){
int []nums ={21,23,65,34,97};
// 外层循环,它决定一共走几趟
for (int i = 0; i < nums.length-1; i++) {
// 内层循环,它决定每趟走一次
for (int j = 0; j < nums.length-i-1; j++) {
// 如果后一个大于前一个
if (nums[j]<nums[j+1]) {
// 换位
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i]+",");
}
}
}
35、自动装箱与拆箱
装箱:将基本类型用它们对应的引用类型包装起来
拆箱:将包装类型转换为基本数据类型
Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作
36、接口是否可以继承接口?抽象类是否可以实现接口?抽象类是否可以继承实体类?
- 接口是否可以继承接口?
可以继承,eg:List就继承了Collection接口
- 抽象类是否可以实现接口?
可以
- 抽象类是否可以继承实体类?
可以,所有抽象类,都继承了Object
37、throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
throws
:用在方法声明上面,表示该方法有可能抛出某个异常throw
:抛出一个指定的异常try catch
:在try中有可能会抛出某个异常,一旦某个异常抛出后,就会在catch
中进行捕捉,一般成对出现finally
:无论是否捕捉异常,都会执行, eg:关闭资源