Java面试题1

发布时间 2023-11-02 18:18:34作者: 喜欢七岁就很浪

Java面试题(第一天)

1.JDK、JRE、JVM三者区别和联系

区别:

JDK:Java Development Kit(Java开发环境)

JRE:Java Runtime Environment(Java运行环境)

JVM:Java Virtual Machine(Java虚拟机)

联系:
image-20230907211853387

.java文件被javac编译成.class文件然后被jvm使用lib类库编译为机器码然后通过jvm映射到操作系统中!

2.面向对象

什么是面向对象?

对比面向过程,是两种不同的处理问题的角度

面向过程更加注重一个事情的每一个步骤和顺序,面向对象更加注重事情有哪些参与者(对象),以及各自需要做什么

比如:洗衣机洗衣服

面向过程一般会将任务解成一系列的步骤(函数):打开洗衣机--->放衣服--->放洗衣粉--->清洗---->烘干

面向对象会拆成人和洗衣机两个对象:
人:打开洗衣机 放衣服 放洗衣粉

洗衣机:清洗 烘干

以上例子可以看出,面向过程比较直接高效,而面向对象更易于复用、扩展和维护。

面向对象三大特性

1.封装

封装的意义,在于明确指出外部使用的所有成员函数和数据项

内部细节对外部调用透明,外部调用无需关心内部的实现

例子:
a.javabean的属性私有,提供get/set对外访问,因为属性的赋值或者获取逻辑只能由javabean本身决定,而不能有外部胡乱修改:

public class User {
    private String name;
    public User() {
    }
    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = "qisui"+name;
    }
}

比如在这里set赋值的时候我需要为名字加上一个前缀,就是由javabean本身控制!

b.ORM框架

操作数据库,我们不需要关系连接如何建立的,sql如何执行,只需要引入mybatis,调用方法即可!

2.继承

继承基类的方法,并且做出自己的扩展或者改变!

子类共性的方法或者属性直接用父类的,而不需要自己去再定义,只需要扩展自己个性化的即可

3.多态

基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。

父类类型 变量名 = new 子类对象;
变量名.方法名();

实际调用的子类中重写过的父类方法或者是父类自己有的方法,无法调用子类特有的功能。

3.==和equals

==:比较的是栈中的值,基本数据类型比较的是变量值,引用数据类型比较的是内存对象的地址

equals:在object中也是用的==来比较,但是一般要重写

Object:

public boolean equals(Object obj) {
    return (this == obj);
}

String:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

例题:

String str1="hello";					//在常量池
String str2 = new String("hello");		 //堆中新开辟一个地址
String str3=str2;					    //指向同一个地址	
System.out.println(str1==str2);//false
System.out.println(str1==str3);//false
System.out.println(str2==str3);//true
System.out.println(str1.equals(str2));//true
System.out.println(str1.equals(str3));//true
System.out.println(str2.equals(str3));//true

4.final

1.final作用?

a.当final修饰方法的时候,表明该方法是最终方法,不可以被重写

b.当final修饰类的时候,表明是最终类,不能被继承

c.当final修饰变量的时候,我们也可以叫他为常量,只能被赋值一次

  • final修饰的变量是基本数据类型,那么变量储存的数据值不能发生改变
  • final修饰的变量如果是引用数据类型,你们变量储存的地址值不能发生改变,对象内部可以改变(数组),所以字符串是不可以变的

2.为什么局部内部类和匿名内部类只能访问局部final变量?

public class Test {

    public static void main(String[] args) {
    }
    
    public void test(final int b){
        final int a=10;
        new Thread(){
            public void run(){
                System.out.println(a);
                System.out.println(b);
            } 
        }.start();
    }
}


class OutClass { 
    private int age=12;

    public void outPrint(final int x){
        class InClass{
            public void InPrint(){
                System.out.println(x);
                System.out.println(age);
            }
        }
        new InClass().InPrint();
    }

}


这两段代码片段中我们首先要知道一个问题就是,局部内部类和匿名内部类编译后会生成两个class文件,Test.class,Test1.class

内部类和外部类是同一级别的,内部类不会因为外部类的方法执行完毕了就销毁

Test中主方法虽然执行完毕了,但是内部类的线程并不会立马就是,因为他们是完全独立的两个class文件

如果外部类的方法结束了,但是局部变量就回收了,可是内部类可能还存在引用的时候,这时候就访问了一个不存在的值,所以就将局部变量复制了一份在内部类的成员变量位置,这里就又有个问题,为了保持两个变量的唯一性和一致性,所以就加上final不让你对这个变量进行修改!

5.String、StringBuffer、StringBuilder

1.区别和使用场景

String是final修饰的,不可变的,每次操作都会产生一个新的String对象

StringBuffer和StringBuilder都是在原对象上操作

StringBuffer是线程安全的,StringBuilder线程是不安全的

StringBuffer方法都是synchronized修饰的

性能:StringBuilder > StringBuffer > String

场景:经常需要改变字符串内容时候使用后面两个

所有场景优先使用StringBuilder,多线程使用需要共享变量时候使用StringBuffer