• Java面试题--Java基础


    1.JDK和JRE有什么区别

    • JDK:Java Development Kit,Java开发工具包,提供了Java的开发环境和运行环境,包括Java编译器、Java运行时环境,以及常用的Java类库等。
    • JRE:Java Runtime Environment,Java运行环境,提供Java运行所需环境=lib+jvm
    • JVM:Java虚拟机,是JRE的一部分,实现跨平台的核心部分

    avatar

    2.==和equals的区别

    (1)对于基本类型和引用类型,==是不同的:

    • 对基本类型使用==:看值是否一样(基础类型包括:byte,boolean,char,short,int,float,long,double)
    • 对引用类型使用==:看引用是否一样(String类型是引用类型,不是基本类型,但是String重写了equals方法,不代表别的引用类型实现了equals方法)

    (2)equals本质上就是==,只不过String,Integer等重写了equals,把它变成了值比较

    代码示例:

    String x = "string";
    String y = "string";
    String z = new String("string");
    System.out.println(x==y);//true
    System.out.println(x==z);//false
    System.out.println(x.equals(y));//true
    System.out.println(x.equals(z));//true
    

    3.两个对象的hashCode()相同,但是equals()不一定是true。是存在hashCode相同但是equals()不为true的情况的

    String x = "通话";
    String y = "重地";
    System.out.println(x.hashCode());//1179395
    System.out.println(y.hashCode());//1179395
    System.out.println(x.equals(y));//false
    

    4.重写equals()时,总要重写hashCode()

    为什么要重写hashCode()和equals()

    5.final关键字的作用

    • 作用在类上时:该类不可被继承
    • 作用在方法上时:该方法不可被重写
    • 作用在变量上时:final修饰的变量叫常量,常量必须被初始化,而且初始化之后值就不能修改

    6.Math.round(11.5)等于多少? Math.round(-11.5)等于多少?

    float f=3.4;是不正确的。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。

    7.Java字符串

    • String声明不可变对象,每次操作都会产生新的String对象,然后将指针指向新的String对象
    • StringBuilder和StringBuffer可以在原有字符串基础上修改
    • 性能StringBuilder > StringBuffer
    • StringBuffer是线程安全的,StringBuilder不是线程安全的
    • 反转字符串的方法:利用StringBuilder和StringBuffer中的reverse()方法

    8.String类常用方法

    • length()
    • indexOf()
    • charAt()
    • substring():substring(start):从start到尾;substring(start,end):从start到end-1
    • equals()
    • replace()
    • trim():删除头尾空白符的字符串
    • split()

    9.String y = "string"和String z = new String("string")一样吗?

    不一样,内存分配方式不一样。String y = "string"放在常量池中,String z = new String("string")会被分配到堆内存中

    10.Java中变量存储的位置

    1.寄存器:最快的存储区,由编译器根据需求进行分配,在程序中无法控制.
    2.栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中)
    3.堆:存放所有new出来的对象
    4.静态域:存放静态成员(static定义的)
    5.常量池:存放字符串常量和基本类型常量(public static final)
    6.非RAM存储:硬盘等永久存储空间

    主要关心栈,堆和常量池。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
    对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份

    局部变量必须初始化。
    形式参数是局部变量,局部变量的数据存在于栈内存中。栈内存中的局部变量随着方法的消失而消失。
    成员变量存储在堆中的对象里面,由垃圾回收器负责回收。

    String x = new String("string")中x是对象引用放在栈中,对象String("string")存放在堆中

    11.抽象类

    1.抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

    2.抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    3.抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

    4.构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

    5.抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

    12.接口

    1.除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

    2.一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。

    3.接口和类的相似点

    • 一个接口可以有多个方法。
    • 接口文件保存在 .java 结尾的文件中,文件名使用接口名。
    • 接口的字节码文件保存在 .class 结尾的文件中。
    • 接口相应的字节码文件必须在与包名称相匹配的目录结构中。

    4.接口和类区别

    • 接口不能用于实例化对象。
    • 接口没有构造方法。
    • 接口中所有的方法必须是抽象方法。
    • 接口不能包含成员变量,除了 static 和 final 变量。
    • 接口不是被类继承了,而是要被类实现
    • 接口支持多继承

    5.接口的特点

    • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字 ,接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字 , 接口中的方法都是公有的
    • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)
    • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法

    6.抽象类与接口的区别:JDK 1.8 以后,接口里可以有静态方法和方法体了

    • 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行
    • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的
    • 一个类只能继承一个抽象类,而一个类却可以实现多个接口

    7.接口是允许多继承的(一个接口可以继承多个其他接口)

    8.标记接口

    最常用的继承接口是没有包含任何方法的接口。

    标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。

    标记接口作用:简单形象的说就是给某个对象打个标(盖个戳),使对象拥有某个或某些特权。

    没有任何方法的接口被称为标记接口。标记接口主要用于以下两种目的:

    • 建立一个公共的父接口:

    正如EventListener接口,这是由几十个其他接口扩展的Java API,你可以使用一个标记接口来建立一组接口的父接口。例如:当一个接口继承了EventListener接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。

    • 向一个类添加数据类型:

    这种情况是标记接口最初的目的,实现标记接口的类不需要定义任何接口方法(因为标记接口根本就没有方法),但是该类通过多态性变成一个接口类型。

    13.访问修饰符

    14.&和&&的区别

    &运算符有两种用法:(1)按位与;(2)逻辑与。

    &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。

    注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。

    15.BIO,NIO,AIO 有什么区别?

    • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
    • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
    • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

    详细回答:

    • 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,不过又放弃了。

    16.用HashMap的时候,用String做key有什么好处

    HashMap的内部实现是通过key的hashCode来确定value的位置,因为字符串是不可变的,所以创建字符串时,它的hashcode会被缓存下来,不用再次计算,所以比其他对象要快。

    17.Integer a= 127 与 Integer b = 127相等吗

    对于对象引用类型:==比较的是对象的内存地址

    对于基本数据类型:==比较的是值

    如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false

    public static void main(String[] args) {
        Integer a = new Integer(3);
        Integer b = 3;  // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b); // false 两个引用没有引用同一对象
        System.out.println(a == c); // true a自动拆箱成int类型再和c比较
        System.out.println(b == c); // true
    
        Integer a1 = 128;
        Integer b1 = 128;
        System.out.println(a1 == b1); // false
    
        Integer a2 = 127;
        Integer b2 = 127;
        System.out.println(a2 == b2); // true
    }
    
    
  • 相关阅读:
    hdu2060
    hdu1003
    style属性
    变量与常量
    使用BIgDecimal进行浮点数的精确计算
    CSUST 玩游戏 题解(思维+优先队列维护第k大)
    百度之星 迷失 题解(矩阵快速幂+分层图)
    CSUST 简单数学题 题解(质因子分解+并查集)
    CSUST 神秘群岛 题解(LCA)
    CSUST lh的简单图论 题解(图转树LCA问题)
  • 原文地址:https://www.cnblogs.com/swifthao/p/12765497.html
Copyright © 2020-2023  润新知