java面试题详细版

一、Java 基础

1解释下什么是面向对象?面向对象和面向过程的区别?

面向对象是以数据为中心,而面向过程以功能为中心

面向过程:就是分析出解决问题所需要的步骤,然后用函数把这些问题一步一步的实现,然后再
使用的时候依次调用就可以了。(简单来说就是每个方法看做一个过程)
列如
放衣服(方法)-人加衣服(方法)-清洗(方法)

面向对象:就是把构成问题的事物分解成各个对象,构建对象的目的不是来完成一个步骤的 ,而
是为了描述某个事物在解决整个问题的步骤中的行为。(简单来说就是执行自己的方法 问题得到解决)
列如
new出二个对象 人和洗衣机

人加入属性跟方法
洗衣机加入属性和方法
执行
人. 放衣服-人.加洗衣粉(方法) - 洗衣机.漂洗(方法)-洗衣机.甩干(方法)

面向对象:基于对象,方法是类
面向过程: 基于算法,方法是 函数/过程
面向对象的三个基本特征是:封装、继承、多态
在这里插入图片描述

2. 面向对象的三大特性?分别解释下?

有封装、继承、多态。

封装是指在一个类中,将属性隐藏起来,只给外界提供公共的访问方式,这样隐藏了事务的事现
细节、提高了代码的复用性和安全性;

继承是指发生在两个类之间,一个类继承另一个类是说这个类属于另一个类,具有另一个类的所
有属性和方法,父类的私有的属性子类无法直接使用,子类无法继承父类的构造方法,但可以调
用,同时它还可以有另一个类不具备的方法和属性;

多态是指建立在继承的基础上的,一般是父类指向子类或者接口指向实现类,一个父类对象可以产生多个不同的子类对象,根据这些子类对象的不同可以具备不同的方法,也就是说表现出了不同的形态即多态。
多态中的成员变量访问原则是:编译的时候看父类有没有,运行的时候使用的是父类的成员变量值;
成员方法的访问原则是:编译的时候看父类有没有,运行的 时候看子类使
用子类的方法。

补充

接口和抽象类的区别:
1.接口的方法默认为public abstract ,接口中的变量默认为public static final,在java8之前所有的方法不能有实现
抽象类中可以有非抽象方法
2.一个类可以实现多个接口,但只能继承一个抽象类
3.一个类实现接口,要实现该接口的所有抽象方法。
4.接口不能被实例化,但可以声明,但是必须引用一个实现该接口的对象。
抽象类可以有构造方法,但是不能被直接通过new进行实例化。但可以通过子类继承,实例化子类的时候抽象类也会被实例化。
这其实用到了多态,向上转型。父类引用指向子类对象。
5.从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范

3. JDK、JRE、JVM 三者之间的关系?

Jvm 是 java 虚拟机,是运行所有 java 程序的家乡计算机,是 java 程序的运行环境,我们写的 java
程序都运行在 jvm 上;

Jre 是 java 程序的运行时环境,包含 jvm 和运行时所需要的核心类库;

Jdk 是 java 程序开发工具包,包含 Jre 和一些开发工具,例如 javac.exe 就是 java 的编译器和
javadoc.exe 可以自动生成代码的说明文档;

三者关系就是:jre 包含了运行类库和 jvm,jdk 包含了开发工具和 jre

4. 平台无关性如何实现

Java 源文件首先会被编译成字节码,再由不同平台的 JVM 进行解析,java 语言在不同平台运行时不需要进行重新编译,java 虚拟机在执行字节码的时候,把字节码转化成平台上的机器指令

6. 重载和重写的区别? (Override 和 Overload)*

重载: 发生在同一个类中,方法名必须相同,参数类型不同或个数不同,方法返回值和访问修饰符可以不同,发生在编译时。

public class Father {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");
    }
    public void sayHello() {
        System.out.println("Hello");
    }
    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。

public class Father {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Son s = new Son();
        s.sayHello();
    }
    public void sayHello() {
        System.out.println("Hello");
    }
}
class Son extends Father{
    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hello by ");
    }
}

这里是转载 (https://blog.csdn.net/plazilan/article/details/107960993?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162216341716780274137625%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162216341716780274137625&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-2-107960993.first_rank_v2_pc_rank_v29&utm_term=%E9%87%8D%E5%86%99%E5%92%8C%E9%87%8D%E8%BD%BD%E7%9A%84%E5%8C%BA%E5%88%AB&spm=1018.2226.3001.4187)

*7. Java 中是否可以重写一个 private 或者 static 方法?

private 和 static 都不可以被重写。首先对于被 private 修饰的方法都会被隐式的指定成
final,所以 private 修饰的方法只能在当前类中使用,如果是其他的类继承当前类是不能访问
到 private 修饰的方法的。

抽象类跟接口区别

抽象类存在普通成员的函数 只能继承一个
成员变量的可以是各种类型

在这里插入图片描述

目的: 在于代码的复用性
接口存在public abstart方法 接口可以实现多个
接口的成员变量的只能是 public static final类型
目的: 在于对类进行约束
在这里插入图片描述
list与set区别
list 有序的 可重复的 允许多个null

set 无序 不可重复的 最多允许一个null 取元素只能用iterator接口取得所有元素 在追个遍历

hashCode equals区别
如果二个对象相等 hashcode一定相同
二个对象,对二个对象分别调用equal方法都返回true
二个对象有相同的hashcode的值 他们不一定相等
equals方法被覆盖过 那么hashcode必须被覆盖

== 和 equals 的区别是什么

==:比较的是两个字符串内存地址(堆内存)的数值是否相等,属于数值比较;
equals():比较的是两个字符串的内容,属于内容比较。

arraylist跟likedlist区别

arrylist 查询速度快 插入跟删除比较慢 动态数组

linkedlist 插入跟删除比较快 查询比较慢 链表

final 在 java 中有什么作用?
final的修饰值不变 修饰类不可继承 修饰方法可以被继承 不可重写

.java 中的 Math.round(-1.5) 等于多少?
-1

Math.round()方法即为我们常说的“四舍五入”方法
Math.round(1.0) 1
Math.round(1.4) 1
Math.round(1.5) 2
Math.round(1.6) 2

Math.round(-1.0) -1
Math.round(-1.4) -1
Math.round(-1.5) -1
Math.round(-1.6) -2

向下取整”实际上就是Math.floor()方法

Math.floor(1.0) == 1.0
Math.floor(1.4) == 1.0
Math.floor(1.5) == 1.0
Math.floor(1.6) == 1.0
Math.floor(-1.0) == -1.0
Math.floor(-1.4) == -2.0
Math.floor(-1.5) == -2.0
Math.floor(-1.6) == -2.0

Math.ceil()方法,表示“向上取整

Math.ceil(1.0) == 1.0
Math.ceil(1.4) == 2.0
Math.ceil(1.5) == 2.0
Math.ceil(1.6) == 2.0
Math.ceil(-1.0) == -1.0
Math.ceil(-1.4) == -1.0
Math.ceil(-1.5) == -1.0
Math.ceil(-1.6) == -1.0

String 属于基础的数据类型吗?
String不是基本的数据类型,是final修饰的java类,是引用类型

在这里插入图片描述
基础类型与引用类型的区别是,基础类型只表示简单的字符或数字,引用类型可以是任何复杂的数据结构 基本类型仅表示简单的数据类型,引用类型可以表示复杂的数据类型,还可以操作这种数据类型的行为 java虚拟机处理基础类型与引用类型的方式是不一样的,对于基本类型,java虚拟机会为其分配数据类型实际占用的内存空间, 而对于引用类型变量,他仅仅是一个指向堆区中某个实例的指针

集合
(1)可以动态保存任意多个对象,使用比较方便!
(2)提供了一系列方便的操作对象的方法: add, remove, set, get等
(3)使用集合添加,删除新元素的示意代码-简洁了
注意:集合中只能存储引用类型数据,如果要存储基本类型数据可以选用包装类。
在这里插入图片描述

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/2731d4cab2ec4fea924f33936e95ed4a.png#pic_center
在这里插入图片描述
File
在这里插入图片描述
java 中操作字符串都有哪些类?它们之间有什么区别?

string StringBuffer 和 StringBuilder

StringBuffer 线程安全 效率低

StringBuilder 线程不安全 效率高、

.String类型进行修改操作之后相当于重新创建对象,StringBuffer和StringBuilder进行增删操作都是针对同一个对象.

StringBuffer中的大部分方法都没有使用synchronized关键字修饰,所以性能更高.单线程情况下首选使用StringBuffer类,多线程环境下需要使用StringBuilder类保证线程安全.

如果字符串声明之后不需要进行改动,则直接声明String类是最好的选择,不使用new关键字声明String对象时,它不会再堆内存中开辟空间,而是直接指向String常量池.这样可以实现复用,降低资源消耗.

String 类的常用方法都有那些

1)int length():返回字符串的长度:return value.length
2)char charAt(int index):返回某索引处的字符return value[index]

3)boolean isEmpty():判断是否是空字符串: return value.length == o
4)String toLowerCase():使用默认语言环境,将 String中的所有字符转换为小写

5)String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写

6)String trim():返回字符革代副本,忽略前导空白和尾部空白
7)boolean equals(Object obj):比较字符串的内容是否相同
8)boolean equalslgnoreCase(String anotherString): 'jequals方法类似,忽略大小写
9)String concat(String str):将指定字符串连接到此字符串的结尾。等价于用“+”

10)int compareTo(String anotherString):比较两个字符串的大小
11)String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
12)String substring(int beginIndex, int endIndex):返回一个新字符串,它是此字符串从beginlndex开始截取到endIndex(不包含)的一个子字符串。

如何将字符串反转?
1 StringBuilder的reverse()方法

public static String reverse2(String s) {

  int length = s.length();

  String reverse = "";

  for(int i = 0; i < length; i++)

  reverse = s.charAt(i) + reverse;

  return reverse;

}

2通过String类的charAt()的方法来获取字符串中的每一个字符,然后将其拼接为一个新的字符串。

/**
	  * 该方法是通过charAt()方法获得每一个char的字符,i=0时获得第一个字符a然后赋值给reverse
	  * 此时reverse="a";i=1时获得第二个字符b然后加上reverse再赋值给reverse,此时reverse="ba";
	  * 一次类推
	  */3
	 public static String CharAtreverse(String s) {
	      int length = s.length();
	      String reverse = "";
	      for (int i=0; i<length; i++)
	          reverse = s.charAt(i) + reverse;
	      return reverse;
	  }

3 通过String的 toCharArray()方法可以获得字符串中的每一个字符串并转换为字符数组,然后用一个空的字符串从后向前一个个的拼接成新的字符串。

public static String reverseCharArray(String s) {
	      char[] array = s.toCharArray();
	      String reverse = "";
	      for (int i = array.length - 1; i >= 0; i--) {
	          reverse += array[i];
	      }
	      return reverse;
	  }

4 递归

Throw 和 Throws 的区别

一:位置不同。throws用在函数上,后边跟的是异常类,可以跟多个异常类。throw用在函数内,后面跟的是异常对象。

二:功能不同。①throws用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先得处理方式。throw抛出具体的问题对象,执行到throw。功能就已经结束了跳转到调用者,并将具体的问题对象抛给调用者,也就是说throw语句独立存在时,下面不要定义其他语句,因为执行不到。②throws表示出现异常的一种可能性,并不一定会发生这些异常,throw则是抛出了异常,执行throw则一定抛出了某种异常对象。

相同点:

两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。

package com.apesource.exception;
 
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.sql.SQLException;
 
public class Demo01 {
	public static void main(String[] args) throws IOException, NullPointerException, SQLException, NoSuchAlgorithmException {
		dosth1();
		dosth2();
		SecureRandom.getInstanceStrong();
	}
	
	// 定义方法时,throws声明该方法可能抛出的异常类型
	// 抛出的异常类型,RuntimeException类或其子类,则该方法调用时,异常可以不处理
	public static void dosth1() throws NullPointerException,SQLException{}
	
	// 抛出的异常类型,如果不是RuntimeException类或其子类,则该方法调用时,异常必须处理,
	public static void dosth2() throws IOException,StringIndexOutOfBoundsException{}
	
	
}
**```
throw**
```c
public class ThrowDemo {
    public static void main(String[] args) {
        //创建一个数组 
        int[] arr = {2,4,52,2};
        //根据索引找对应的元素 
        int index = 4;
        int element = getElement(arr, index);

        System.out.println(element);
        System.out.println("over");
    }
    /*
     * 根据 索引找到数组中对应的元素
     */
    public static int getElement(int[] arr,int index){ 
       	//判断  索引是否越界
        if(index<0 || index>arr.length-1){
             /*
             判断条件如果满足,当执行完throw抛出异常对象后,方法已经无法继续运算。
             这时就会结束当前方法的执行,并将异常告知给调用者。这时就需要通过异常来解决。 
              */
             throw new ArrayIndexOutOfBoundsException("哥们,角标越界了~~~");
        }
        int element = arr[index];
        return element;
    }
}

反射
获取Class类实例的四种方法

package com.apesource.exception;
 
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.sql.SQLException;
 
public class Demo01 {
	public static void main(String[] args) throws IOException, NullPointerException, SQLException, NoSuchAlgorithmException {
		dosth1();
		dosth2();
		SecureRandom.getInstanceStrong();
	}
	
	// 定义方法时,throws声明该方法可能抛出的异常类型
	// 抛出的异常类型,RuntimeException类或其子类,则该方法调用时,异常可以不处理
	public static void dosth1() throws NullPointerException,SQLException{}
	
	// 抛出的异常类型,如果不是RuntimeException类或其子类,则该方法调用时,异常必须处理,
	public static void dosth2() throws IOException,StringIndexOutOfBoundsException{}
	
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值