ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

牛客网部分面试题整理

2021-06-15 15:57:40  阅读:110  来源: 互联网

标签:面试题 变量 对象 重写 equals 牛客 整理 方法 public


一、关键字

(一)Java里面的final关键字是怎么用的?

final可以用来修饰类、类方法、以及变量

当用final修饰一个类时,表明这个类不能被继承;
修饰类方法时,则该方法不能被继承。也不能被重写;
修饰变量时,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

(二)关于Synchronized和lock ?

  synchronized是Java的关键字,是内置的语言实现;当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。如果发生了异常,synchronized会自动释放线程占有的锁,因此不会导致死锁现象发生;
  Lock是一个接口,在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁。

此外,Lock是显式锁,需要手动开启和关闭锁,而synchronized是隐式锁,出了作用域自动释放;Lock只有代码块锁,而synchonized有代码块锁和方法锁。

(三)volatile

详细内容参考:https://www.cnblogs.com/dolphin0520/p/3920373.html

1.介绍一下volatile?

volatile关键字与Java的内存模型有关,是用来保证程序的有序性和可见性的。
我们所写的代码,不一定是按照我们自己写的顺序来执行,因为编译器会做重排序。重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。所以为了保证程序按写的顺序执行,就需要加volatile关键字,禁止重排序。而一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

2)禁止进行指令重排序。
  
那如何保证有序性呢?
是通过插入内存屏障来保证的。这里要知道happens-before 原则,其中有一条就是volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作。

如何保证可见性?
首先Java内存模型分为,主内存,工作内存。比如线程A从主内存把变量从主内存读到了自己的工作内存中,做了加1的操作,但是此时没有将i的最新值刷新回主内存中,线程B此时读到的还是i的旧值。而如果加了volatile关键字时,它能保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。

PS:
1.重排序:处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同你写的代码中的顺序一致,但是它会保证程序最终结果和代码顺序执行的结果是一致的。重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

2.有序性:即程序执行的顺序按照代码的先后顺序执行
在java中可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。另外,Java内存模型具备一些先天的“有序性”,即不需要通过任何手段就能够得到保证的有序性,这个通常也称为 happens-before 原则。其中有一条就是volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作。

3.可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
当一个共享变量被volatile修饰时,它能保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。
另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。

4.加入volatile关键字的代码生成的汇编代码会多出一个lock前缀指令,lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

2)它会强制将对缓存的修改操作立即写入主存;

3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

2.volatile关键字解决了什么问题?实现原理是什么?

解决了:

 1.保证了变量的可见性

 2.禁止指令重排序

实现原理:

是内存屏障。作用是:
 1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成。总之一句话,它能保证指令按照我们希望的顺序执行
 2)它会强制将对缓存的修改操作立即写入主存(可见性);
 3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

(四)static

1.static关键字是什么意思?Java中是否可以覆盖(override)一个是static的方法?

static关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。

Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
private只能够被自身类访问,子类不能访问private修饰的成员,所以也不能override一个private方法。

PS;静态绑定和动态绑定
在进行方法调用时,系统唯一的任务是确定被调用方法的版本。对于private、static、final方法或者构造器,这部分方法在程序真正运行之前就有一个可以确定的调用版本,并且该版本在运行期间是不可变的,编译器一开始就能确定要调用的版本,这叫做静态绑定,这些方法在类加载的时候就会把符号引用转化为该方法的直接引用。
与之对应,在程序运行期间确定方法调用版本的调用方式叫做动态绑定,此时,虚拟机会为每个类创建一个方法表,列出所有方法签名和实际调用的方法,这样一来虚拟机在调用方法时,只用查找该表就行了,只有在调用时采用动态绑定的方法才能体现出多态特性。

2.是否可以在static环境中访问非static变量?

不能。在静态中不能调用费静态,因为静态优先于非静态存在于内存中,当静态调用时,费静态还没有进入内存,没办法调用。

3.静态变量存在什么位置?

方法区

修饰符权限:

四大修饰符,分别为private,default,protected,public

  • private可以修饰成员变量,成员方法,构造方法,不能修饰类(此刻指的是外部类,内部类不加以考虑)。被private修饰的成员只能在其修饰的本类中访问,在其他类中不能调用,但是被private修饰的成员可以通过set和get方法向外界提供访问方式
  • default(默认的)
    defalut即不写任何关键字,它可以修饰类,成员变量,成员方法,构造方法。被默认权限修饰后,其只能被本类以及同包下的其他类访问。
  • protected(受保护的)
    protected可以修饰成员变量,成员方法,构造方法,但不能修饰类(此处指的是外部类,内部类不加以考虑)。被protected修饰后,只能被同包下的其他类访问。如果不同包下的类要访问被protected修饰的成员,这个类必须是其子类。
  • public(公共的)
    public是权限最大的修饰符,他可以修饰类,成员变量,成员方法,构造方法。被public修饰后,可以再任何一个类中,不管同不同包,任意使用。

也就是:private在本类,defaule在本包,proetected在本包或者其他包中的子类,public任意包中的任意类

二、面向对象

面向对象的五大基本原则:
单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。
依赖倒置原则(Dependecy-Inversion Principle):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。
接口隔离原则(Interface-Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口。

总结:
s( Single-Resposibility Principle ): 单一职责原则
o( Open-Closed principle ): 开放封闭原则
l( Liskov-Substituion Principle ): 里氏原则
i( Interface-Segregation Principle ): 接口隔离原则
d( Dependecy-Inversion Principle ): 依赖倒置原则
一个单词:立方体(solid),很好记!!!

(一)hashCode()和equals()相关

1.两个对象值相同(x.equals(y) == true),但却可有不同的hashcode,该说法是否正确,为什么?

答:不对,Java对象的eqauls方法和hashCode方法是这样规定的:

➀相等(相同)的对象必须具有相等的哈希码(或者散列码)。

➁hashCode()相等的两个对象他们的equal()不一定相等。

此外equals()不相等的两个对象,hashcode()有可能相等(我的理解是由于哈希码在生成的时候产生冲突造成的)。反过来,hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。

2.为什么重写equals?

重写equals方法的目的是判断两个对象的内容(内容可以有很多,比如同时比较姓名和年龄,同时相同的才是同一个对象)是否相同

如果不重写equals,那么默认比较的是对象的引用是否指向同一块内存地址,重写之后目的是为了比较两个对象的value值是否相等。(要注意的是,利用equals比较八大包装对象(如int,float等)和String类(因为该类已重写了equals和hashcode方法)对象时,默认比较的是值,在比较其它自定义对象时都是比较的引用地址。)

比如现在有两个Student对象:

Student s1=new Student("小明",18);
Student s2=new Student("小明",18);

如果不重写equals,这个时候比较的就是两个对象的地址,结果当然是false,因为new了2个对象内存地址肯定不一样而重写之后,比较的就是两个对象的内容,结果是true。

3.为什么重写equals还要重写hashcode?

在hashMap中,如果使用自定义对象作为HashMap的key来使用时,是先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等的。若equals()不相等则认为他们不相等。也就是说,只有两个都相等时,才能映射到同一个key!!

object中equals默认比较的是内存地址,hashcode默认比较的是内存地址的哈希值。如果equals重写了,比如说是基于对象的内容实现的,它为true时两个对象的内存地址并不一定相同(比如上面的两个student对象),这个时候,如果不重写hashcode,因为两个对象的内存地址不同,所以他们的hashcode值并不一定相同。就导致两个对象equals相等但是hashcode不相等。这样,当你用其中的一个对象作为键保存到hashMap、hashTable或hashSet中,再以“相等的”另一个作为键值去查找他们的时候,则根本找不到。(一个对象应用hashmap作为key时他们是先判断hashcode是否相等再比较equals,不相等就为不同的key)

HashMap用来判断key是否相等的方法,其实是调用了HashSet来判断加入的元素是否相等。重载hashCode()是为了对同一个key,能得到相同的HashCode,这样HashMap就可以定位到我们指定的key上。重载equals()是为了向HashMap表明当前对象和key上所保存的对象是相等的,这样我们才真正地获得了这个key所对应的这个键值对。

实例:

package com.yang.Pool;

import java.util.HashMap;

public class Test {

    public static void main(String []args){
        HashMap<Person,String> map = new HashMap<Person, String>();
        Person person1 = new Person(1234,"乔峰");
        Person person2 = new Person(1234,"乔峰");
        //判断equals是否相等
        System.out.println("person1和person2是否相等: "+ person1.equals(person2));
        //put到hashmap中去
        map.put(person1,"天龙八部");
        //get取出,从逻辑上讲应该能输出“天龙八部”
        System.out.println("结果:"+map.get(person2));
    }
}


class Person{
    int idCard;
    String name;

    public Person(int idCard, String name) {
        this.idCard = idCard;
        this.name = name;
    }
    //重写equals
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()){
            return false;
        }
        Person person = (Person) obj;
        //两个对象是否等值,通过idCard来确定
        return this.idCard == person.idCard && this.name == person.name;
    }
}

在这里插入图片描述
尽管我们在进行get和put操作的时候,使用的key从逻辑上讲是等值的(通过equals比较是相等的),但由于没有重写hashCode方法,所以put操作时,key(person1的hashcode1)–>hash–>indexFor–>最终索引位置 ,而通过key取出value的时候 key(person2的hashcode2)–>hash–>indexFor–>最终索引位置,由于hashcode1不等于hashcode2,导致没有定位到一个数组位置而返回逻辑上错误的值null(也有可能碰巧定位到一个数组位置,但是也会判断其entry的hash值是否相等,上面get方法中有提到。)

所以,在重写equals方法的时候,必须注意重写hashCode方法,同时还要保证通过equals判断相等的两个对象,调用hashCode方法要返回同样的整数值。而如果equals判断不相等的两个对象,其hashCode可以相同(只不过会发生哈希冲突,应尽量避免)。

重写hashCode后:

package com.yang.Pool;

import java.util.HashMap;

public class Test {

    public static void main(String []args){
        HashMap<Person,String> map = new HashMap<Person, String>();
        Person person1 = new Person(1234,"乔峰");
        Person person2 = new Person(1234,"乔峰");
        //判断equals是否相等
        System.out.println("person1和person2是否相等: "+person1.equals(person2));
        //查看hashcode
        System.out.println("person1的hashcode: "+person1.hashCode());
        System.out.println("person2的hashcode: "+person2.hashCode());
        //put到hashmap中去
        map.put(person1,"天龙八部");
        //get取出,从逻辑上讲应该能输出“天龙八部”
        System.out.println("结果:"+map.get(person2));
    }
}


class Person{
    int idCard;
    String name;

    public Person(int idCard, String name) {
        this.idCard = idCard;
        this.name = name;
    }
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + idCard;
        result = 31 * result + name.hashCode();
        return result;

    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()){
            return false;
        }
        Person person = (Person) obj;
        //两个对象是否等值,通过idCard来确定
        return this.idCard == person.idCard && this.name == person.name;
    }
}

结果:
在这里插入图片描述

(二)判断当一个对象被当作参数传递给一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

参考:https://www.cnblogs.com/sum-41/p/10799555.html

程序中有两种参数传递:

  • 值传递,是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
  • 引用传递,是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

Java中都是值传递,只不过对于引用类型参数,值的内容是对象的引用。 当是基本类型时修改副本不能影响原值,而当是对象时,此时副本是地址,修改的是这个地址指向的对象,所以会影响原对象。(其实并没有定论,有的人说有引用传递,而在Java核心技术卷1和 疯狂java讲义中都说只有值传递)

简单来说就是,当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用(地址)对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

有的时候传递引用参数时,可能会产生引用传递的错觉,是因为参数保存的是实际对象的地址值,你改变的只是地址值指向的堆内存中的实际对象,并没有真正改变参数,参数的地址值没有变。

(三)重载和重写相关

1. 说明Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?

Java中的方法重载发生在同一个类里面,两个或者是多个方法的方法名相同但是参数不同的情况。
方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。

2.说明重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,区别在于重载是一个类中多态性的一种表现,而重写是父类与子类之间多态性的一种表现。

重载发生在同一个类中,如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载,重载与修饰符无关。

重写发生在子类与父类之间,要求子类方法与其父类有相同的名称和参数,且子类方法与父类被重写方法有相同的返回类型,且子类中的方法权限要比必须大于或者等于父类权限访问(比如父类是protected,那子类就要是public或者protected),不能比父类被重写方法声明更多的异常(里氏代换原则)。

Overload的方法可以改变返回值的类型,因为它与返回值类型无关。

PS;四大权限:public --> protected --> default --> private

(四)Java中接口和抽象类的异同?

答:

1.都能包含抽象方法。(jdk1.8之前,接口中只能有抽象方法,抽象类中可以有普通方法。jdk1.8之后,接口中可以定义default、static修饰的方法,即接口中也可以有普通方法了)

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

4.接口中的变量必须给初始值,也就是只有常量,而抽象类中可以不给。

5.抽象类可以有构造方法,接口中不能有构造方法;

6…抽象类中可以有普通成员变量,接口中没有普通成员变量 。

7.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意(也就是说有私有变量),但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

8.抽象类中的抽象方法的访问类型可以是public,private,protected和默认类型,但接口中的抽象方法只能是public类型的。(jdk9之后,接口中可以有private类型的方法)

abstract class和interface所反映出的设计理念不同。其实abstract class表示的是"is-a"关系,interface表示的是"like-a"关系。

注:is-a:继承关系 has-a:从属关系 like-a:组合关系
在这里插入图片描述

(五)内部类可以引用他包含类的成员吗,如果可以,有没有什么限制吗?

一个内部类对象可以访问创建它的外部类对象的内容。内部类如果不是static的,那么它可以访问创建它的外部类对象的所有属性。内部类如果是static的,那么它只可以访问创建它的外部类对象的所有static属性。

(六)Java异常有哪些类型?

Java中所有的异常都继承自Throwable,分为Error和Exception两大类,其中:

Error是系统级错误,在代码层无法处理,常见的有StackOverflowError、OutofMemoryError等;

Exception是异常,通常可以再代码层进行处理,常见的有NullPointerException、IndexOutOfBoundsExecption等。

(七)说明JAVA语言如何进行异常处理?关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

1.Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。

2.一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候就可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。用try来指定一块预防所有”异常”的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的”异常”的类型。throw语句用来明确地抛出一个”异常”,用在方法内部(创建一个异常对象,throw new 异常类名 (参数或者异常信息))。throws用来标明一个成员函数可能抛出的各种”异常”,用在方法定义处。Finally为确保一段代码不管发生什么”异常”都被执行。

3.在try块中可以抛出异常,只是用的很少。可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,”异常“的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种”异常”进行处理,堆栈就会展开,直到遇到有处理这种”异常”的try语句。(在try中嵌try)

(八)说明一下final, finally, finalize的区别?

final 用于声明属性,方法、类和变量。
在方法上:表明这个方法不能被重写。(如果一个类中的方法用了final,在子类继承这个类之后,子类可以使用该方法,但是不能重写)
在类上:表明该类不能有子类,不能被继承。
在变量上:表示该变量不可变。即一次赋值,终生不变,不可以再重写赋值。

finally是异常处理语句结构的一部分,finally中的语句总是会执行。

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

(九)面向对象的特征有哪些方面?

抽象、继承、封装、多态

1.抽象
抽象就是忽略与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不专注于全部问题,而只是选择其中的一部分。抽象包括两个方面,一是过程抽象,二是数据抽象。

2.继承
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的子类,而原始类称为新类的父类。子类可以从它的父类那里继承方法和实例变量,并且子类可以修改或增加新的方法使之更适合特殊的需要。

3.封装
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

4.多态
多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

(十)说明Comparable和Comparator接口的作用以及它们的区别。

它们主要用途都是用来实现排序的

区别是:
1.Comparable接口位于java.lang包下;Comparator接口位于java.util包下。

2.Comparable接口只提供了一个compareTo()方法,用来给两个对象排序;Comparator接口不仅提供了compare()方法和equals()方法,还提供了其他默认方法,如reversed()、thenComparing(),使我们可以按照更多的方式进行排序。

3.如果要用Comparable接口,则必须实现这个接口,并重写comparaTo()方法;但是Comparator接口可以在类外部使用,通过将该接口的一个匿名类对象当做参数传递给Collections.sort()方法或者Arrays.sort()方法实现排序。Comparator体现了一种策略模式,即可以不用要把比较方法嵌入到类中,而是可以单独在类外部使用,这样我们就可有不用改变类本身的代码而实现对类对象进行排序。

(十一)Java是否支持多继承?

Java中类不支持多继承,只支持单继承(即一个类只有一个父类)。 但是java中的接口支持多继承,,即一个子接口可以有多个父接口。

(十二)什么是泛型?

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

public class GenericTest {
  
      public static void main(String[] args) {
          /*
          List list = new ArrayList();
          list.add("qqyumidi");
          list.add("corn");
          list.add(100);
          */
  
         List<String> list = new ArrayList<String>();
         list.add("qqyumidi");
         list.add("corn");
         //list.add(100);   // 1  提示编译错误
  
         for (int i = 0; i < list.size(); i++) {
             String name = list.get(i); // 2
             System.out.println("name:" + name);
         }
     }
 }

采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过List,直接限定了list集合中只能含有String类型的元素,从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。

String、StringBuilder、StringBuffer的区别?

1.操作数量较少的字符串用String,不可修改的字符串;
2.在单线程且操作大量字符串用StringBuilder,速度快,但线程不安全,字符串可修改;
3.在多线程且操作大量字符串用StringButter,线程安全,字符串可修改。

Array和ArrayList的不同点:

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
Array大小是固定的,ArrayList的大小是动态变化的。

标签:面试题,变量,对象,重写,equals,牛客,整理,方法,public
来源: https://blog.csdn.net/Shmily_0/article/details/114182539

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有