Java基础面试

1.面向对象和面向过程的区别

答:面向过程就是分析出解决问题需要的步骤,然后用函数把步骤实现出来,使用的时候一个一个一次调用


image.png

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展。

面向对象就是把问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。


image.png

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态的特性,可以设计出低耦合的系统可以更加灵感、更加易于维护
缺点:性能比面向过程低。

2. Java 语言有哪些特点

1.简单易学
2.面向对象(封装继承多态)
3.跨平台性
4.可靠性
5.安全性
6.支持多线程

3.关于JVM JDK和JRE的解答

JVM
Java虚拟机是运行java字节码的虚拟机,JVM有针对不同系统的特定实现,目的是使用相同的字节码,不同的系统给出的结果一致。

什么是字节码?采用字节码的好处是什么?

在java中,Java程序通过编译成字节码文件(.class文件)也就是计算机可以识别的二进制
它不面向任何特定的处理器,只面向虚拟机。java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植性的特点,所以java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此java程序无须重新编译便可在多种不同的计算机上运行。


image.png

我们需要格外注意的是 .class->机器码 这一步。在这一步 jvm 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的,也就是所谓的热点代码,所以后面引进了 JIT 编译器,JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。

HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。

JDK和JRE

JDK是Java Development Kit,它是功能齐全的Java SDK。它拥有JRE所拥有的一切,还有编译器(javac)和工具(如javadoc和jdb)。它能够创建和编译程序。

JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java虚拟机(JVM),Java类库,java命令和其他的一些基础构件。但是,它不能用于创建新程序。

如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进行一些 Java 编程方面的工作,那么你就需要安装JDK了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是在应用程序服务器中运行Java程序。那你为什么需要JDK呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。

4. Oracle JDK 和 OpenJDK 的对比

对于Java7,没什么区别。OpenJDK项目主要基于Sun捐献的HotSpot源代码。此外,OpenJDK被选为Java7的参考实现,由Orcale工程师维护。关于JVM,JDK,JRE和OpenJDK之间的区别。

问:OpenJDK存储库中的源代码与用于构建Oracle JDK的代码之间有什么区别?Oracle博客帖子在2012年有一个更详细的答案:
答:非常接近-我们的Oracle JDK版本构建过程基于OpenJDK 7构建,只添加了几个部分,例如部署代码,其中包括Oracle的Java插件和Java WebStart的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源Oracle JDK的所有部分,除了我们考虑商业功能的部分。
总结:
1.Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次。
2.OpenJDK是一个参考模型并且是完全开源的,而OracleJDK是OpenJDK的一个实现,并不是完全开源的。
3.Oracle JDK 比OpenJDK更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。
4.在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;

5.Java和c++

1.都是面向对象语言,都支持封装继承多态。
2.Java不提供指针来直接访问内存,程序内存更加安全。
3.Java的类是单继承,C++支持多重继承
;虽然Java的类不可以多继承,但是接口可以多继承。
4.Java有自动内存管理机制,不需要手动释放内存。

6.字符型常量和字符串常量的区别

1.形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
含义上: 字符常量相当于一个整形值( ASCII 值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)
占内存大小 字符常量只占2个字节 字符串常量占若干个字节(至少一个字符结束标志) (注意: char在Java中占两个字节)


image.png

9.构造器Constructor是否可以被override

构造器不能被重写但是可以被重载,因为父类的私有属性和构造方法不能被继承,所以一个类中有多个构造函数。

10.重写和重载的区别

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

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

11. Java 面向对象编程三大特性: 封装 继承 多态

封装:封装就是把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。
继承:继承是使用已经存在的类的定义作为基础建立新的类。新的类的定义可以增加属性和新的方法也可以继承父类属性和方法,但不能选择性的继承父类,继承的好处是能够方便的复用以前的代码。

注意:1.子类拥有父类非private的属性和方法。
2.子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
3.子类可以用自己的方式实现父类的方法。

多态:同一个对象,在不同时刻表现出不同状态。
实现多态的两种形式:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖同一接口的同一方法)

12.String StringBuffer 和 StringBuilder 的区别是什么 String 为什么是不可变的

String是不可变类,String中的对象是不可变的,也就可以理解为常量,线程安全。AstractStringBulider是StringBuilder和StringBuffer的公共父类,定义了一些字符串的基本操作。比如insert,append,indexof等方法。线程安全。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以线程安全,StringBulider并没有对方法加同步锁,所以线程是不安全的。

性能:

每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

三者使用:

1.操作少量数据:String
2.单线程操作字符串缓冲区下操作大量数据:StringBulider
多线程操作字符串缓冲区下操作大量数据 = StringBuffer

13自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来
拆箱:将包装类型转换为基本数据类型。

14.在一个静态方法内调用一个非静态成员为什么是非法的

由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

15.接口和抽象类的区别是什么

接口

接口可以含有变量和方法。接口中的变量会被隐式的制定为public static final变量,而方法会被隐式的指定为public abstract方法且只能是public abstract方式
接口中所有的方法不能有具体的实现,接口中的方法必须是抽象方法。

抽象类

抽象方法,只有声明,而没有具体实现。抽象方法的声明是abstract void fun()
如果一个类含有抽象方法,则这个类成为抽象类,抽象类必须在类前用abstract关键字修饰。

区别:

1.接口的方法默认是public,所以方法在接口中不能有实现(Java 8 开始接口方法可以有默认实现),抽象类可以有非抽象方法。
2.接口中的实例变量默认是final类型的,而抽象类中则不一定
3.一个类可以实现多个接口,但最多只能实现一个抽象类。
4.一个类实现接口的话要实现接口的所以方法,而抽象类不一定。
5.接口不能实例化,但可以声明,但是必须引用一个实现该接口的对象。
备注:在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义了一样的默认方法,必须重写,不然会报错。
关于抽象类
JDK 1.8以前,抽象类的方法默认访问权限为protected
JDK 1.8时,抽象类的方法默认访问权限变为default
关于接口
JDK 1.8以前,接口中的方法必须是public的
JDK 1.8时,接口中的方法可以是public的,也可以是default的
JDK 1.9时,接口中的方法可以是private的

16.== 与 equals(重要)

==:是判断两个对象的地址是不是相等。就是判断两个对象是不是同一个对象。(基本数据类型==比较的值,引用数据类型==比较的内存地址)
equals():作用判断两个对象是否相等。
分为两种情况
1.类没有覆盖equals()方法。通过equal()比较该类的两个对象时,等价于“==”比较两个对象
2.类覆盖equals()

说明:

String 中equals 方法是被重写过的,因为object 的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
当创建String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。
举例:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 为一个引用
        String b = new String("ab"); // b为另一个引用,对象的内容一样
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 从常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一对象 地址不同
            System.out.println("a==b");
        if (a.equals(b)) // true 地址不同内容相同
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

17.hashCode 与 equals (重要)

1.hashCode()介绍
hashCode()的作用是获取哈希码,也成为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中索引位置。hashCode()定义在JDK的Object.java中,这就意味着Java中的任何类都包含hashCode()函数。
散列表存储的键值对(Key-Value),它的特点:能根据"键"快速的检索出对应的“值”。这其中就利用到了散列码。
hashCode()与equals()的相关规定

  1. 如果两个对象相等,则hashcode一定也是相同的
  2. 两个对象相等,对两个对象分别调用equals方法都返回true
  3. 两个对象有相同的hashcode值,它们也不一定是相等的
  4. 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
  5. hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

举例:

    Set<Person> list = new HashSet<>();
        Person person = new Person();
        person.age = 33;
        person.name = "lisi";
        list.add(person);
        Person person1 = new Person();
        person1.age = 33;
        person1.name = "lisi";
        list.add(person1);
//        list.add("3");
//        System.out.println(list.size());
        System.out.println(person.hashCode());
        System.out.println(person1.hashCode());
        System.out.println(person.equals(person1));
        System.out.println(list);
//        List<String> list1 = new ArrayList<>();
//        list1.add("3");
//        list1.add("3");
//        System.out.println(list1.size());
//        System.out.println(list1);
package cn.xxs;

/**
 * Created by wth on 2019/6/24.
 */
public class Person {
    int age;
    String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = age;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
}
//String.java
     *
     * @return  a hash code value for this object.
     */
    public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

image.png

18. 为什么Java中只有值传递

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269