java 基础整理

java基础

  1. 什么是面向对象?谈谈你对面向对象的理解?

    区别于面向过程,面向对象有三大特征:封装、继承、多态;

    封装:将某些信息隐藏在类的内部,向外部提供访问这些信息的方法,方便修改和实现

    继承:可以从原有的类,称之为基类,派生出新的类,称之为子类,子类可以继承父类中的方法和属性,同时也可以对原有的方法进行重写或实现父类中没有的方法以应对不同的需求;

    多态:实现多态需要有三个条件:继承,方法重写,向上转型;子类对从父类中继承的方法进行重写,然后将子类的引用赋给父类对象,这样不同的对象在调用被重写后的同一方法可以有不同的表现,从而实现了多态。例如对于一个父类-图形类,它有一个方法是计算面积,然后两个子类分别是三角形和矩形,这两个子类会对计算面积这个方法进行重写,我们实例化三角形和矩形这两个类,并将对象的引用赋给两个图形类对象,这样这两个不同的图形类对象调用求面积这个方法时会有不同的实现;

  2. 字节序定义以及Java属于哪种字节序?如何判断计算机是大端模式的还是小端模式的?

    定义:将一个多字节的变量存储到内存中时,如果低位字节放在低地址端,高位字节放在高地址端那么就是小端模式;如果高位字节放在低地址端,低位字节放在高地址端那么就是大端模式;

    举例:将int类型的数据 0x12345678存放在内存中时,如果0x78放在低地址端那么就是小端模式,如果0x78放在高地址端那么就是大端模式;

    java:java是大端模式;

    判断方法:java大小端判断

  3. JDK和JRE区别?

    JDK:java开发工具包,提供了java开发和运行时环境;

    JRE:java运行环境,提供了java运行时需要的环境;

    JDK包含JRE,如果只需要运行java程序那么就只需要安装JRE即可

  4. 简述java访问控制符?

    访问控制符的作用

    • 防止对封装数据的未授权访问;
    • 有助于保证数据的完整性;
    • 合理的使用访问控制符可以降低类与类之间的耦合性,从而便于项目的开发和维护;

    private:在当前类中可见;

    default:(为空) 当前包下可见;

    protected:除当前包下可见外,不在同一包下的子类也可见;

    public:当前项目下可见;

    类的访问控制符:只能是default和public。

  5. java代码初始化顺序?

    先后顺序是:父类静态变量 父类静态块 子类静态变量 子类静态块 主程序 父类非静态变量 父类非静态块 父类构造方法 子类非静态变量 子类非静态块 子类构造方法。

  6. 接口和抽象类的相同点和区别?

    相同点

    • 都不能被实例化;
    • 实现类必须实现接口的所有抽象方法,子类必须实现其所继承的抽象类的所有抽象方法;

    不同点

    • 抽象类可以有构造方法,构造方法用于初始化类,也可以被子类调用用于初始化;接口不可以有构造方法;
    • 一个类可以实现多个接口但是只能继承一个抽象类;
    • 抽象类体现的是is-a的关系,接口体现的是can的关系;
    • 接口中的属性都是final修饰的;
  7. 为什么java语言不支持多继承?

    • 为了使程序结构更加清晰;假如java支持多继承,类C继承于类A,和B,如果类A和类B都有一个自定义的的方法 f(), 而在类C中没有对f()进行重写,那么通过类C的对象调用方法f() 时,就会不知道应该调用哪个父类的方法 f()。
    • java语言通过实现多个接口来间接的实现多继承,由于接口中只有方法定义,而没有方法的实现,即使两个接口中同样的方法也不会产生二义性,因为必须要在实现类中对方法进行实现才能调用。
    • 多继承会使得类型转换,和构造方法的调用顺序变得复杂,影响程序性能;
  8. 谈谈你对java提供的多态机制的理解?

    • java多态可以分为编译时多态和运行时多态;
    • 编译时多态指方法重载:指的是在一个类中有多个重名方法,这些方法具有不同的形参列表;通过参数列表来区分不同的方法;
    • 运行时多态指方法重写:继承父类或实现接口时,子类重写父类的方法后,当父类引用指向不同的子类对象时,调用同一被重写后的方法会有不同的实现。
  9. 方法重写与方法重载的区别?

    • 方法重写父类和子类之间的关系,是垂直关系,方法重载是同一个类中方法之间的关系,是水平关系;
    • 方法重写要求参数列表相同,方法重载要求参数列表不同;
    • 方法重写,调用方法是根据具体的对象来调用;方法重载是根据调用时传入的实参列表来决定调用哪个方法;
    • 方法重写要求:方法名相同;参数列表相同;访问控制符不能比父类中的访问控制符低;返回值类型可以不同,但也必须是父类的派生类型;不能抛出新的检查型异常,或者比父类更加宽泛的异常;
    • 方法重载要求:方法名相同;参数列表必须不同;返回值类型可以相同也可以不相同,但是不能以返回值类型作为重载函数的区分标准(这是由于…);
  10. final, finally, finalize的区别是什么?

    • final:主要用于修饰属性,方法,类,表示属性不可变,方法不可重写,类不可继承;
    • finally:作为异常处理的一部分,在try/catch语句后使用,finally代码块常用于需要释放资源(如数据库连接、网络连接和磁盘文件等)的情况下;
    • finalize:是Object类的一个方法,当垃圾回收器准备回收某个对象时,会首先调用这个对象的fianlize方法,使其做生前最后的事情,我们可以重写finalize()方法避免其被回收,但是如果发生下次GC时该对象被判定可以回收,那么就直接回收了,也就是说每个对象的finalize方法最多只会被调用一次。
  11. 出现在java程序中的finally代码块是否一定会执行?

    • 当遇到以下情况时不会执行:
      • 进入try块之前就已经发生了异常;
      • 当程序在try块中强制退出时,如调用System.exit(0),也不会执行下面的finally代码块;
    • 其他情况下:
      • 当有异常发生时:try块先执行,然后进行异常处理,接着执行finally代码块后程序结束;
      • 当没有异常发生时,try块先执行,然后执行finally代码块,接着执行下面的代码块;
      • (一般考察选择题)如果try或catch语句中有return语句并且对变量有修改,那么fianlly代码块会在return之前被执行变量的值会先保存在一个临时空间;如果finally代码块也有return语句,并且对变量值也做了修改,那么将会刷新临时空间的值,也就是覆盖了try或catch块中的语句。举例
  12. java中static关键字的作用是什么?

    • 可以为属性或者方法创建一个与对象个数无关的存储空间;
    • 使用static修饰的属性或者方法不需要通过对象,而是直接可以通过类名来调用;
    • static可以修饰代码块,jvm在加载类的时候会执行静态代码块,这可用于类的初始化,static代码块只会执行一次;
    • static 可以修饰内部类,静态内部类可以不需要外部类的实例而实例化;静态内部类可以访问外部类的静态属性和方法不能访问非静态属性和非静态方法;
  13. java代码块执行顺序?

    • 父类静态块;(只会执行一次)
    • 子类静态块;(只会执行一次)
    • 父类非静态块;
    • 父类构造方法;
    • 子类非静态块;
    • 子类构造方法;
    • 普通代码块。
  14. java中一维数组和二维数组声明方式?

    • 一维数组:

      • dtype[] arr1 = {};         
        dtype[] arr2 = new int[10];
        dtype[] arr3 = new int[] {1,2,3};
        
        dtype arr4[] = {};
        dtype arr5[] = new int[10];
        dtype arr6[] = new int[] {1,2,3};
        
    • 二维数组:

      • dtype arr7[][] = {};
        dtype[] arr8[] = {};
        dtype[][] arr9 = {};
        
  15. String和StringBuffer有什么区别?

    • String是不可变类,其属性value被final修饰,因此String对象一旦被创建其值将不可改变;
    • StirngBuffer是可变类,其对象被创建后,仍然可以对其值进行修改;StringBuffer是线程安全的,StringBuilder是线程不安全的;
  16. ==(等号) 和equals的区别?

    • 如果是基本数据类型,那等号比较的是值;如果是引用数据类型那么等号比较的就是两个对象是否在同一块存储空间;
    • equals方法是Object类提供的方法之一,因为所有的类都是默认继承Object方法的,所以每个对象都有equals方法;Object类提供的equals方法是直接调用等号来比较对象的;通过对equals方法重写,可以实现比较对象的内容而不是在内存中的地址,比较对象的内容相对来说更有意义。
  17. 为什么要把String设计为不变量?

    • 节省空间:String对象保存在字符串常量池中,如果字符串对象已经存在字符串常量池中,就不会创建新的对象而是返回原有对象的引用,这样比较高效且节省空间;
    • 提高效率:由于其不可变性,在多线程环境中不需要同步操作,提高效率;
    • 提高安全性:String常用于用户名,密码,文件名,其不可变性,可以防止被恶意篡改;
  18. 序列化是什么?序列化怎么实现?参考1 参考2

    • 定义及作用:序列化是将对象转化为字节序列的过程;序列化可以将对象的状态信息转化为序列来进行网络传输,或者保存到文件,数据库中,并在需要的时候将序列读取出来重新构造一个与原来相同的对象,称为反序列化。

    • 如何实现:实现Serializable接口(里面没有定义任何方法,只是一个标记接口)的类才能被实例化,通过对象输出流的writeObject方法实现序列化,通过对象输入流的readObject方法实现反序列化;

    • 标记接口:标记接口是没有任何方法和属性的接口。标记接口不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型。标记接口在Java语言中有一些很著名的应用,比如java.io.Serializable和java.rmi.Remote等接口便是标记接口。标记接口,当一个类实现了一个标记接口之后就像是给自己打了个标签。

    • 序列化ID(seriaVersionUID)的作用:这个作用是:在进行反序列化时jvm会把传过来的字节流中的序列化ID和本地类中的序列化ID进行对比,如果两个ID不一致就会抛出异常;如果类中没有定义这个序列化ID的话,JVM会在编译时根据类自动生成一个序列化ID,但是后续如果对类进行了修改,这时再反序列化就抛出序列化ID不一致的异常,反序列化也就失败了。

    • 其它:静态变量不可以序列化,因为序列化的是堆中的对象,静态变量从属于类,且不在堆内存中(之后看java虚拟机机时再来斟酌这一句话);序列化对象是十六进制表示。

    • 代码:

       import java.io.FileInputStream;
       import java.io.FileOutputStream;
       import java.io.ObjectInputStream;
       import java.io.ObjectOutputStream;
       import java.io.Serializable;
       
       public class Learn1 {
       	public static void main(String[] args) throws Exception {
       		// 序列化
       		System.out.println("......开始序列化....................");
               ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e://A.txt"));
               A a = new A(2, 12);
               
               oos.writeObject(a);
               oos.flush();
               oos.close();
               System.out.println(".......序列化结束...................");
               
               //反序列化
               System.out.println(".......开始反序列化.................");
               ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e://A.txt"));
               A an = (A) ois.readObject();   // 序列化生成的流里面是不包含静态变量的;
               ois.close();
               an.print();
               System.out.println(".......反序列化结束................");
       	}
       }
       
       class A implements Serializable {     // 需要实现serialicable接口
       	private int i;
       	private static int num_static = 10;
       	public int num = 156;
       	public static final long serialVersionUID=1234L;   
       	
       	public void print() {
       		System.out.println("i:" + i + "num_static: " + num_static);
       	}
       	
       	public A(int i, int num_static) {
       		this.i = i;
       		this.num_static = num_static;
       		System.out.println("A: 带参数的构造方法附加静态变量");
       	}
       }
      
  19. 简述java中的Class对象?

    • java中的对象可以分为实例对象和Class对象,每一个类都有唯一的一个Class对象;
    • 当JVM加载一个类的时候就会创建一个代表这个类的Class对象,这个对象用于程序访问方法区中该类的各种数据的接口。
    • 获取Class对象的方法:
      • 对象.getClass();
      • 类名.class
      • Class.forName(包名.类名")
    • Class对象主要用于反射;
  20. java的反射机制是什么?

    • 编译期和运行期:

      • 编译期:指的是将源码交给编译器编译成计算机可以执行的文件的过程,java中就是把java源文件编译成字节码文件的过程,编译期只是做一些翻译,语法检查等方面的工作,并没有把文件放在内存中执行。
      • 运行期:就是将编译后的文件放入计算机内存中执行。
    • java反射机制指的是在程序运行的过程中可以 构造任意一个类的对象获取类的属性和方法获取对象所属的类调用任意一个对象的方法

    • 优点和缺点:

      • 优点:反射机制使得java具有动态获取程序的信息动态调用对象方法的能力,提高系统的灵活性;
      • 缺点:反射会消耗一定的系统资源;反射在调用方法时可以忽略类型检查,可以调用类的私有方法和属性,因此可能会因破坏了类的封装性而导致安全问题。
    • 反射API:

      • Class类:可以获得类的属性和方法
      • Field类:可以获得类的属性
      • Method类:获取类的方法信息
      • Construct类:获取类的构造方法等信息
  21. 简述注解

    • 注解都是以@符号开始的,比如用于方法重写的那个@Override,注解也属于一种类型;
    • 注解不会改变程序的运行结果,也不会影响程序的运行性能;
    • 注解的作用:
      • 生成帮助文档;
      • 跟踪代码依赖性,实现代替配置文件的功能(后续学到Spring框架时再来细看);
      • 进行格式检查,比如将@Override放在方法前,如果该方法并不是重写了父类方法,那么编译器会报错,这样可以避免一些因单词拼写错误而带来的问题。
  22. 简述元注解(难点

    • 元注解是负责对其他注解进行说明的注解;
    • 元注解有哪些:
      • @Retention:表示注解的生命周期;其参数Source, Class, Runtime,分别表示在源文件中有效,在类中有效,在运行时有效。如果需要在运行时动态获取注解的信息,那只能使用Runtime,如果只是做一些检查型的工作那就使用Source
      • @Target:用来指定一个注解的使用范围,其参数有Field(用于成员变量), Construtor(用于构造器), Method(用于方法), Package(用于包), Local_Variable(用于局部变量), Type(用于类,接口)
      • @Documented:是一个标记注解,其修饰的注解类会被Javadoc工具提取成文档。
      • @Inherited: 是一个标记注解,被Inherited注解的注解可以被子类继承。
      • @Repeatable:被元注解修饰的注解可以同时作用一个对象多次,但是每次又可以代表不同的含义;
  23. 简述java的异常:Error和Exception

    • Error是程序无法处理的错误;Exception程序本身可以处理的异常,一般需要捕获并进行处理,这两个类均继承Throwable类;
    • 常见的Error有:
      • 栈溢出错误;
      • 内存溢出错误;
    • Exception分为运行时异常(可不检查型异常)和非运行时异常(检查型异常)
      • 对于运行时异常可以通过try catch进行捕获,也可以不捕获;
        • 空指针异常
        • 类型转换异常
        • 数组下标越界异常
      • 对于非运行时异常必须进行处理,否则编译不通过;
        • IO操作异常
        • 找不到指定类异常
  24. 简述throws和throw的区别

    • throw:用在方法体内部,throw语句一定会抛出一个的异常对象。
    • throws:用来声明一个方法可能产生的所有异常,不做任何处理,而是将异常向上传递,谁调用就抛给谁;
      • 一般用在方法声明后面,其后面跟的是异常类名,异常类名可以有多个,彼此用逗号隔开,
      • 抛出异常,不做处理,由该方法的调用者来处理
      • throws 语句不一定会发生异常,只是有发生异常的可能性;
  25. 简述泛型和泛型擦除

    • 泛型:泛型的本质就是参数化类型。

      • 可以为类或者接口指定一个类型参数,通过这个类型参数来限制所操作的数据类型,从而保证类型转换的绝对安全。

      • 泛型作用于方法(泛型方法):泛型方法就是不显式的指定方法的参数类型,而是在使用该方法时才确定数据类型,这样带来的好处就是方法可以接受不同类型的输入参数,减少了冗余代码。

    • 泛型擦除:java编译器生成的字节码文件是不包含泛型信息的,泛型类信息在编译时被擦除,这个过程就是泛型擦除。

  26. 简述java基本数据类型

    • byte:占用1个字节,取值范围是 -128 ~ 127
    • short:占用2个字节,取值范围是 - 2 15 2^{15} 215~ 2 15 2^{15} 215-1
    • char:占用2个字节,取值范围是 - 2 15 2^{15} 215~ 2 15 2^{15} 215-1
    • int:占用4个字节,取值范围是 - 2 31 2^{31} 231~ 2 31 2^{31} 231-1
    • long:占用8个字节,取值范围是 - 2 63 2^{63} 263~ 2 63 2^{63} 263-1
    • float:占用4个字节,取值范围是 - 2 31 2^{31} 231~ 2 31 2^{31} 231-1
    • double:占用8个字节,取值范围是 - 2 63 2^{63} 263~ 2 63 2^{63} 263-1
    • boolean:单独使用使占用4个字节,boolean型数组中每个元素占用1个字节。
  27. 简述自动装箱和自动拆箱

    • java的基本数据类型均对应一个包装类型;
    • 将包装类型转化为基本数据类型称为自动拆箱,如 int -> Integer,将基本数据类型转化为包装类型称为自动装箱 Integer-> int。
  28. 简述Object常用方法

    • hashcode():通过对象计算出散列码,多用于map或者equals方法;对于同一个对象多次调用该方法返回的整型值是一样的;
    • equals():用于判断两个引用变量是否引用同一个对象,但一般都是重写后的方法用于比较两个引用变量所引用的两个对象是否具有相同的内容;
    • toString():返回对象的字符串表示, 具体表示是类名+@+对象的哈希值的十六进制表示
    • clone():深拷贝一个方法,相比于浅拷贝直接传递引用,深拷贝是重新创建一个对象,赋以被拷贝对象的值,因此对clone出来的对象进行操作不会改变原对象的值;
    • finalize():是Object类的一个方法,当垃圾回收器准备回收某个对象时,会首先调用这个对象的fianlize方法,使其做生前最后的事情,我们可以重写finalize()方法避免其被回收,但是如果发生下次GC时该对象被判定可以回收,那么就直接回收了,也就是说每个对象的finalize方法最多只会被调用一次。
    • wait():持有对象锁的线程释放锁和CPU使用权,进入等待;
    • notify():持有对象锁的线程A准备释放锁,并通知JVM唤醒某个竞争该对象的线程B,直至线程A的synchronized代码作用域结束,线程B获得对象锁资源,其他线程继续等待,直至新的notify(),或notifyall()发出。
    • notifyall():持有对象锁的线程A准备释放锁,通知JVM唤醒所有在等待该对象锁的线程,多个线程会竞争该锁,最终只会有一个线程得到,该线程执行完毕释放锁后,剩余线程继续竞争。
  29. 简述内部类及其作用

    • 成员内部类:作为外部类的成员对象。
      • 内部类中可以访问外部类的所有方法和属性,
      • 外部类中不能直接访问内部类的方法和属性,必须通过内部类的实例来访问;
      • 在外部类以外或者外部类的静态静态方法中需要通过外部类的实例来创建内部类实例;其他地方不需要,比如同在一个外部类下的其它成员内部类中以及外部类的非静态方法中;
        class Inner1 {
        }
        Inner1 i = new Inner1();     // 不需要创建外部类实例
        public void method1() {
        	Inner1 i = new Inner1(); // 不需要创建外部类实例
        }
        public static void method2() {
        	Inner1 i = new Outter().new Inner1(); // 需要创建外部类实例
        }
        class Inner2 {
        	Inner1 i = new Inner1(); // 不需要创建外部类实例
        }
        
    • 局部内部类:类似于局部变量,不能使用 public protect private static 修饰,存在于方法内部,只在当前方法有效,不能在当前方法以外的地方被实例化;
    • 匿名内部类:只能使用一次,没有类名。通常用于继承一个类重写其方法,实现一个接口,实现其方法,匿名内部类通常用于扩展一个类,对于某些只会使用一次类,使用匿名内部类会使得代码更加精简。比如我们在使用Thread实现多线程的时候,当需要对Thread的run方法进行重写时,使用匿名内部类可以不用重新定义一个类,使得代码更加简洁。
    • 静态内部类:静态内部类可以不需要外部类的实例而实例化;静态内部类可以访问外部类的静态属性和方法不能访问非静态属性和非静态方法;
  30. 简述java的List,Set?

    • List:是一个有序集合,java有两种常见实现方式,分别是ArrayList和LinkedList
      • ArrayList 参考:底层使用数组存储数据,是容量可变的非线程安全的列表,支持随机访问,集合扩容时会将原有数据复制到新数组中;
      • LinkedList:底层使用双向链表来存储数据,不支持随机访问,插入删除速度较快;
    • Set:不允许元素重复的无序集合;
      • HashSet:使用HashMap实现,HashMap的Key即为HashSet存储的元素;value是一个常量;判断元素相同时首先调用hashCode方法,相同之后再调用equals方法;
      • LinkedHashSet:继承自HashSet, 底层使用LinkedHashMap实现,使用双向链表来维护元素插入顺序;
      • TreeSet:使用TreeMap实现,底层数据结构是使用红黑树实现,添加元素到集合时,按照比较规则插入,保证插入后元素仍然是有序的,查询时间复杂度是O(log n);
  31. 简述HashMap,为何HashMap不安全?

    • JDK8以前底层实现是数组+链表,JDK8以后改为数组+链表/红黑树;
    • HashMap中数据是以键值对形式存在,通过计算键对应的哈希值,得到该键值对在数组中的存放下标,如果两个数据的键对应的哈希值一样,就会发生哈希冲突,那么将会被放到同一个链表,如果数组长度大于64,并且某个下标对应的链表长度大于8,那么链表将会转化为红黑树;
    • 链表的每个节点含有四个成员变量,分别是key, value, hash, next。
    • 如果当前数据总数/当前数组容量大于负载因子,将会对数组进行扩容;数组的默认初始化容量为16,扩容必须是2的倍数,最大容量为 2 30 2^{30} 230
    • 负载因子为什么是0.75,为什么不选择其他值;
      • 当数组中元素个数大于 数组总容量*负载因子 时,将会进行扩容,由于数组容量总是2的倍数,从这个角度来看选择0.5, 0.75,1比较合适,因为这时两者相乘能保证阈值是整数;
      • 当负载因子为0.5时,确实进一步降低了哈希冲突的概率,但是也浪费了一半的存储空间;
      • 当负载因子为1时,最大化的利用了存储空间,但是也增加了哈希冲突的概率;
      • 从上面分析来看,选用0.75确实是一种折衷方案,兼顾了降低哈希冲突的概率和最大化利用存储空间。
    • hashmap是线程不安全的(难点):
      • jdk7时,由于数组扩容时使用头插法实现,导致并发情况下会产生环形链表,导致查询时出现死循环。参考1 参考2
      • jdk8虽然使用尾插法避免了产生环形链表,但是并发环境下使用put方法仍会使得后一个key值覆盖前一个key值;
      • 由于扩容机制的存在,也会存在A线程执行扩容后,B线程使用get获取数据出错的情况;
  32. 简述java红黑树和自平衡树?

    • 红黑树:什么是红黑树
      • 红黑树是一种近似平衡的二叉查找树,它能够保证从根节点到叶子结点的最长路径不会长于最短路径的两倍。
      • 首先它是一个二叉查找树;
      • 每个节点要么是红色要么是黑色;
      • 根节点必须是黑色;
      • 红色节点不能连续,也就是红色节点的孩子节点和双亲节点都不能是红色;
      • 从每个节点到树尾端的任何路径都含有相同个数的黑色节点;
    • 自平衡树:
      • 每个节点都有一个值用于记录其左右子树的高度差,如果高度差超过1就需要进行调整;
    • 两者的优势:
      • AVL更适合查询,因为相比于红黑树其更加平衡;
      • 红黑树插入和删除比较快,因为相比于AVL树其可能调整次数相对较少;
  33. 简述TreeMap?

    • TreeMap底层使用红黑树实现,其插入删除的时间复杂度与红黑树相同都是O(logn),这在性能上是低于hashmap的,但是TreeMap可以实现按键值大小有序输出而hashmap不行。
  34. java线程安全的基本数据结构有哪些?

    • Hashtable:在方法之前增加了snchronized关键字,保证方法是同步的;
    • ConcurrentHashMap:HashMap线程安全版本;效率较高用于替代Hashtable 参考
    • Vector:线程安全版的ArrayList;
    • Stack:线程安全版的栈;
    • BlockingQueue :线程安全版的队列;
  35. Collections和Collection有什么区别?

    • Collection是一个集合接口,它提供了对集合对象进行基本操作的方法定义,所有集合都是它的子接口,像List,Set都是其子接口。
    • Collections是一个作为一个工具类使用,不允许被实例化,它的构造方法是私有的。它提供了很多静态方法,像sort(), reverse()等方法;(与之相似的还有一个Arrays工具类)
  36. java语言特点:

    • 纯面向对象:java是纯面向对象的语言
    • 平台无关:java语言可以实现一次编写到处运行,也就是在windows上可以运行的代码,同样可以不加修改的运行在其他操作系统上面。背后支撑机制就是Java虚拟机,因为java程序的运行需要通过Java虚拟机来实现,只要在不同的操作系统上面安装对应的java虚拟机,那么java虚拟机会负责将源码编译后的字节码文件解释成为与平台相对应的机器语言,然后运行。
    • 其它:提供垃圾回收,异常处理等机制,有丰富的类库,支持多线程,网络通信。
  37. ArrayList, LinkedList, Vector有什么共同点和区别?

    • 共同点:
      • ArrayList, LinkedList, Vector都是可变长度的动态数组;
    • 不同点:
      • ArrayList和Vector都是基于数组实现的,支持随机访问,但是插入和删除元素可能需要移动容器中已有的元素,插入删除的效率较低,当容器中元素个数超过容器的最大容量后,会进行扩容操作;
      • Vector是线程安全的,其大部分方法都是直接或间接同步的,ArrayList和LinkedList都是非线程安全的;
      • LinkedList是基于双向链表实现的,对数据的索引需要从头开始遍历链表,因此随机访问效率较低,但在插入和删除元素时不需要移动元素,因此插入和删除的效率较高;
  38. HashMap和Hashtable有什么区别?

    • 两者都实现了map接口;
    • HashMap是Hashtable的轻量级实现,HashMap允许key和value为空,但是key只能有一个为空;但是Hashtable不允许为空的key和value;
    • Hashtable中的方法是线程安全的,而HashMap不是,所以多线程访问HashMap中的方法时需要提供额外的同步机制;
    • Hashtable继承自Dictionary类,遍历元素时使用Enumeration,HashMap继承自AbstractMap类,遍历元素时使用Iterator。
    • 计算hash值的方式不同,Hashtable直接使用对象的hashCode()方法返回的值,HashMap为了减少hash冲突,又对hashCode()返回的值做了位运算;这是由于通过hashCode()方法计算出的值低位相同的概率较高,通过位运算处理来降低发生冲突的概率。
  39. 如何决定是使用HashMap还是使用TreeMap?

    • 如果对进行的插入删除一个元素更为频繁,那么使用HashMap更为合理;
    • 如果需要对Key集合进行有序的遍历那么需要使用TreeMap;
  40. fail-fast和fail-safe迭代器的区别?

    • fail-fast迭代器直接在原容器上面进行,如果在遍历的过程中,发现容器结构发生变化,比如增加或删除元素,就会立刻抛出ConcurrentModificationException异常,而仅仅是修改元素则不会抛出异常;常见的Fail-Fast迭代器有HashMap和ArrayList;
    • fail-safe迭代器的遍历基于原容器的一个克隆,因此对容器进行修改不影响遍历;常见的使用fail-safe迭代器有ConcurrentHashMap。
  41. HashSet, equals,hashCode之间的关系?

    • equals:用于比较两个引用变量是否引用同一个对象;一般通过重写将其修改为判断两个引用变量所引用的两个对象是否具有相同的内容;
    • hashCode:返回对象的hash值,不同对象的hash值肯定不同,但具有相同hash值的对象不一定相等,这是由于使用的hash函数可能会发生hash碰撞;
    • HashSet集合里面保证元素是不重复的,主要是通过equals()和hashCode()两个方法实现,
      • 首先如果两个对象的hashCode值不等,那么两个对象不同;
      • 如果两个对象的hashCode值相等,那么会继续调用equals方法判断,如果返回true那么两个对象相同,否则不同。
  42. java加号的作用?

    int a = 10;
    int b = 24;
    System.out.println(10+24);    // 输出34
    System.out.println("10"+24);  // 输出1024
    System.out.println("sum:" + a+b);    // 输出 sum:1024
    System.out.println("sum:" + (a+b));  // 输出 sum:34 
    

参考

http://interviewtop.top/#/list

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值