八股文系列- Java面试题第一套

大家好,我是青空。

最近又赶上跳槽的高峰期,好多粉丝,都问我要有没有最新面试题,能不能做一些分享,和做一些面试题解析的系列文章。

青空收到消息之后,觉得这个建议挺不错的。那我就计划简单及概念性的面试题就多个面试题汇总成一片文章,比较复杂的面试题就单独拎出来讲讲。

文末领取面试大全

1、Java语言主要特性

1、简单性

Java设计者在设计Java的时候尽可能的接近于C++,但又剔除了C++中很少使用、难以理解、易混淆的特性,使得大多数程序员很容易学习和使用Java

2、面向对象

Java面向对象特性和C++旗鼓相当,但是Java为了减少复杂度,不支持类的多重继承,只支持接口的多重继承。

3、分布式

Java有丰富的网络库用于处理HTTP和FTP之类的 TCP/IP 协议,能够使用URL打开和访问网络上的对象

4、健壮性

Java在设计过程中,花了很大的精力去做早期的问题检测、后期运行时检测,并消除了容易出错的情况。相比C++,Java中采用的指针模型可以消除重写内存和损坏数据的可能性。

5、安全性

Java通常被用于网络环境中,Java为此提供了一套安全机制防止病毒和恶意篡改系统。

6、体系结构中立

Java程序通过编译器生成一个体系结构总理的目标文件格式(class文件)。可以在任何Java运行时系统中运行。

7、可移植性

Java的规范中没有“依赖具体实现”的地方,在任何平台任何系统中,所有的数据类型都是同意的。

8、解释型

Java解释器可以在任何移植了解释器的机器上执行 Java 字节码。

9、高性能

解释后的字节码性能已经非常满意。相比其他解释型的语言,Java的性能还是不错的。

10、多线程

Java原生支持多线程。通过Thread相关类可以带来更好的交互响应。

11、动态性

Java的库中可以自由地添加新方法和实例变量,且不会对客户端有任何影响。

2、JDK 和 JRE 的区别?

  • JDK 是 Java Development Kit 的首字母缩写,是提供给 Java 程序员的开发工具包,换句话说,没有 JDK, Java 程序员就无法使用 Java 语言编写 Java 程序。也就是说,JDK 是用于开发 Java 程序的最小环境。

  • JRE 是 Java Runtime Environment 的首字母缩写,是提供给 Java 程序运行的最小环境,换句话说,没有 JRE,Java 程序就无法运行。

3、面向对象都有哪些特性以及你对这些特性的理解

  • 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。

  • 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。

  • 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调 用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。

4、new 一个对象的过程和 clone 一个对象的过程区别

  • new 操作符的本意是分配内存。程序执行到 new 操作符时,首先去看 new 操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。

  • clone 在第一步是和 new 相似的,都是分配内存,调用 clone 方法时,分配的内存和原对象(即调用 clone 方法 的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后,clone 方法返回,一个新的相同 的对象被创建,同样可以把这个新对象的引用发布到外部。

5、& 和 && 的区别

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

  • &&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是 true 整个表达式的值才是 true。

6、== 和 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

因为 x 和 y 指向的是同一个引用,所以 == 也是 true,而 new String()方法则重写开辟了内存空间,所以 == 结果为 false,而 equals 比较的一直是值,所以结果都为 true。

equals

equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较。看下面的代码就明白了。

首先来看默认情况下 equals 比较一个有相同值的对象,代码如下:

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

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Cat c1 = new Cat("ross");
Cat c2 = new Cat("ross");
System.out.println(c1.equals(c2)); // false

输出结果出乎我们的意料,竟然是 false?这是怎么回事,看了 equals 源码就知道了,源码如下:

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

原来 equals 本质上就是 ==。

那问题来了,两个相同值的 String 对象,为什么返回的是 true?代码如下:

String s1 = new String("ross");
String s2 = new String("ross");
System.out.println(s1.equals(s2)); // true

同样的,当我们进入 String 的 equals 方法,找到了答案,代码如下:

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 重写了 Object 的 equals 方法,把引用比较改成了值比较。

总结

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

7、Java 中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?

  • 方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。

  • 方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。

8、Java 中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?

当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提 供构造函数的情况下,Java 编译器会为这个类创建一个默认的构造函数。

Java 中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数 必须有它自己唯一的参数列表。

Java 不支持像 C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情 况下,Java 不会创建默认的复制构造函数。

9、Java 支持多继承么?

不支持,Java 不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。

10、接口和抽象类的区别是什么?

Java 提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:

  • 接口中所有的方法隐含的都是抽象的。

  • 抽象类则可以同时包含抽象和非抽象的方法。

类可以实现很多个接口,但是只能继承一个抽象类。

类如果要实现一个接口,它必须要实现接口声明的所有方法。但是类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。抽象类可以在不提供接口方法实现的情况下实现接口。

Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。

Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protected 或者 是 public。接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。

11、什么是值传递和引用传递?

对象被值传递,意味着传递了对象的一个副本。因此,就算是改变 了对象副本,也不会影响 源对象的值。

对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用 。因此,外部对引用对 象所做的改变会反映到所有的对象上。

12、进程和线程的区别是什么?

进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

13、创建线程有几种不同的方式?你喜欢哪一种?为什么?

有三种方式可以用来创建线程:

  • 继承 Thread 类

  • 实现 Runnable 接口

  • 应用程序可以使用 Executor 框架来创建线程池

实现 Runnable 接口这种方式更受欢迎,因为这不需要继承 Thread 类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而 Java 不支持多继承),只能实现接口。同时,线 程池也是非常高效的,很容易实现和使用。

14、概括的解释下线程的几种可用状态。

线程在执行过程中,可以处于下面几种状态:

  • 就绪(Runnable):线程准备运行,不一定立马就能开始执行。

  • 运行中(Running):进程正在执行线程的代码。

  • 等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。

  • 睡眠中(Sleeping):线程被强制睡眠。

  • I/O 阻塞(Blocked on I/O):等待 I/O 操作完成。

  • 同步阻塞(Blocked on Synchronization):等待获取锁。

  • 死亡(Dead):线程完成了执行。

15、同步方法和同步代码块的区别是什么?

在 Java 语言中,每一个对象有一把锁。线程可以使用 synchronized 关键字来获取对象上的锁。synchronized 关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。

16、在监视器(Monitor)内部,是如何做线程同步的?程序应该做哪种级别的同步?

监视器和锁在 Java 虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许 执行同步代码。

17、什么是死锁(deadlock)?

两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程 都陷入了无限的等待中。

18、如何确保 N 个线程可以访问 N 个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程 按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出 现死锁了。

19、Java中final、finally、finalize的区别与用法

  • final: 修饰符(关键字);如果一个类被声明为 final,意味着它不能再派生出新的子类,不能作为 父类被继承,因此一个类不能既被声明为 abstract 的,又被声明为 final 的; 将变量或方法声明为 final,可 以保证它们在使用中不被改变; 被声明为 final 的变量必须在声明时给定初值,而在以后的引用中只能读取, 不可修改; 被声明为 final 的方法也同样只能使用,不能重载。

  • finally: 在异常处理时提供 finally 块来执行 任何清除操作; 如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如 果有的话)。

  • finalize: 方法名; Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之 前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

20、成员变量与局部变量的区别有哪些?

  1. 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成 员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。

  2. 从变量在内存中的存储方式来看:如果成员变量是使用 static 修饰的,那么这个成员变量是属 于类的,如果没有使用 static 修饰,这个成员变量是属于实例的。对象存于堆内存,如果局部 变量类型为基本数据类型,那么存储在栈内存,如果为引用数据类型,那存放的是指向堆内存对 象的引用或者是指向常量池中的地址。

  3. 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。

  4. 成员变量如果没有被赋初始值:则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。

参考资料

《Java核心技术卷一》

面试大全包括:包括 Java 集合、JVM、多线程、并发编程、设计模式、SpringBoot、SpringCloud、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、Python、HTML、CSS、Vue、React、JavaScript、Android 大数据、阿里巴巴等大厂面试题等、等技术栈!

领取方式:扫描下方公众号【蚂蚁原图】回复【面试题】即可获取

八股文系列- Java面试题第一套_第1张图片
来源: https://mp.weixin.qq.com/s/Met3-y1E21PR-NqvBi8FwQ

你可能感兴趣的:(Java,/,Kotlin,二三事,java,面试)