Java:基础面试题

文章目录

面向对象三大特征的说明

  • 面向对象有三大特点:封装、继承、多态。(如果要回答四个,可加上 抽象性 这一特点)
    1. 继承性:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
    2. 封装性:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
    3. 多态性:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
    4. 抽象性:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

Java的内存管理之垃圾回收

  • 分配:由JVM自动为其分配相应的内存空间
  • 释放:由JVM提供垃圾回收机制自动的释放内存空间
  • 垃圾回收机制(GC:Garbage Collection):将垃圾对象所占用的堆内存进行回收。Java的垃圾回收机制是JVM提供的能力,由单独的系统级垃圾回收线程在空闲时间以不定时的方式动态回收。
  • 垃圾对象:不再被任何引用指向的对象。

在程序中是否可以通知垃圾回收机制过来回收垃圾?

  • 能,通过调用System.gc();或Runtime.getRuntime().gc();

调用了System.gc();或Runtime.getRuntime().gc();后是立刻执行垃圾回收吗?

  • 不是,该调用并不会立刻启动垃圾回收机制开始回收,但会加快垃圾回收机制的运行。

垃圾回收机制关键点

  • 垃圾回收机制只回收JVM堆内存里的对象空间
  • 对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力;现在的JVM有多种垃圾回收实现算法,表现各异
  • 垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行
  • 可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象
  • 程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定
  • 垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)
  • 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用

构造器Constructor是否可被override

  • 构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload

java类是否可以多继承,怎么实现多继承?

  • java没有多继承,但可以通过接口的形式来达到多继承的目地

以下程序输出结果是什么

class A {
    int a = 1;
    double d = 2.0;

    void show() {
        System.out.println("Class A: a=" + a + "\td=" + d);
    }
}

class B extends A {
    float a = 3.0f;
    String d = "Java program.";

    void show() {
        super.show();
        System.out.println("Class B: a=" + a + "\td=" + d);
    }
}
public class Test{
    public static void main(String[] args) {
        A a = new A();
        a.show();

        A b = new B();
        b.show();
    }
}

Class A: a=1 d=2.0
Class A: a=1 d=2.0
Class B: a=3.0 d=Java program.

重载(overload)和重写(overried,也叫做“覆盖”)的区别?

  • 方法的重写Overriding和重载Overloading是Java多态性的不同表现。
  • 重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。
  • 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。

Overload的方法是否可以改变返回值的类型?

  • Overloaded的方法是可以改变返回值的类型

输出以下程序的结果

class Super {
	public int get() {
		return 4;
	}
}

class Demo15 extends Super {
	public long get() {
		return 5;
	}

	public static void main(String[] args) {
		Super s = new Demo15();
		System.out.println(s.get());
	}
}

编译失败,因为子类父类中的get方法没有覆盖。但是子类调用时候不能明确返回的值是什么类型。所以这样的函数不可以存在子父类中。

比较两个String总是false,但是它们明明都是"abc"

  • 比较String一定要使用equalsequalsIgnoreCase方法,不要使用 ==
  • ==比较的是两个引用(变量)是否指向了同一个对象,而不是比较其内容。

==和equals()的区别是什么

  • ==既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
  • equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点
  • 具体要看自定义类里有没有重写Object的equals方法来判断
  • 通常情况下,重写equals方法,会比较类中的相应属性是否都相等

int 和 Integer 有什么区别

  • Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。
  • int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。
  • 原始类型封装类型及其对应的包装类:boolean Boolean,char Character,byte Byte,short Short,int Integer,long Long,float Float,doubl Double
  • 引用类型和原始类型的行为完全不同,并且它们具有不同的语义。
  • 引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。

abstract class 和interface 有什么区别?

  • 声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法
  • 接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口

接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?

  • 接口可以继承接口。抽象类可以实现(implements)接口,
    抽象类可继承实体类,但实体类必须不能是如下两种情况之一:
    1. final修饰符修饰的类是不能的
    2. 如果此实体类有且仅有私有的构造函数也是不能的。

Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)

  • 匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现

谈谈final, finally, finalize的区别

  • final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
  • finally—在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)
  • finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的

abstract 能修饰哪些结构? 修饰以后,有什么特点?

  • 类不能实例化,提供子类
  • 抽象方法,只定义了一种功能的标准。具体的执行,需要子类去实现

抽象类和接口有哪些共同点和区别?

  • 相同点:不能实例化,都可以被继承
  • 不同点:抽象类:有构造器。 接口:不能声明构造器
  • 多继承vs 单继承
区别点抽象类接口
定义包含抽象方法的类主要是抽象方法和全局常量的集合
组成构造方法、抽象方法、普通方法、常量、变量常量、抽象方法(JDK8:默认方法、静态方法)
使用子类继承抽象类(extends)子类实现接口(implements)
关系抽象类可以实现多个接口接口不能继承抽象类,但允许继承多个接口
常见设计模式模板方法简单工厂、工厂方法、代理模式
对象都通过对象的对泰兴产生实例化对象
局限抽象类有单继承的局限接口没有此局限
实际作为一个模板是作为一个标准或表示一种能力
选择如果抽象类和接口都可以使用的话,优先使用接口,因为避免单继承的问题如果抽象类和接口都可以使用的话,优先使用接口,因为避免单继承的问题

判断输出结果

@Test
public void testString(){
    String str1 = "ceshi";
    String str2 = "ceshi";
    String str3 = new String("ceshi");
    System.out.println(str1 == str2);//true
    System.out.println(str1 == str3);//false
    System.out.println(str1.equals(str3));//true
    str1 = "ceshi123.com";
    String str4 = "123.com";
    String str5 = "ceshi" + "123.com";
    System.out.println(str1 == str5);//true

    String str6 = (str2 + str4).intern();
    System.out.println(str1 == str6);//true
}

String s = new String(“xyz”);创建了几个String Object

  • 两个,一个字符对象,一个字符对象引用对象

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

  • Math.round(11.5)12;Math.round(-11.5)-11;round方法返回与参数最接近的长整数,参数加1/2后求其floor

是否可以继承String类

  • String类是final类故不可以继承

String与StringBuffer的区别

  • String的长度是不可变的,StringBuffer的长度是可变的。
  • 如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法

运行时异常与一般异常有何异同

  • 异常表示程序运行过程中可能出现的非正常状态
  • 运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

Java中的异常处理机制的简单原理和应用

  • 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。

违反语义规则包括2种情况

  • 一种是JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException
  • 另一种情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类。

垃圾回收的优点和原理。并考虑2种回收机制

  • Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。
  • 垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

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

  • Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。

  • 在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。

  • Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。

    1. 用try来指定一块预防所有"异常"的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的"异常"的类型。
    2. throw语句用来明确地抛出一个"异常"。
    3. throws用来标明一个成员函数可能抛出的各种"异常"。
    4. finally为确保一段代码不管发生什么"异常"都被执行一段代码。
  • 可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常"的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到有处理这种"异常"的try语句。

try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?

  • 会执行,在return前执行

列举一些最常见到的runntime exception

名称描述
ArithmeticException算术异常
ArrayStoreException将数组类型不兼容的赋值给数组元素时抛出的异常
BufferOverflowException缓冲区溢出异常
BufferUnderflowException,缓冲区下溢异常
ClassCastException类型强制转换异常
ClassNotFoundException类没找到时,抛出该异常
FileNotFoundException文件未找到异常
IllegalArgumentException传递非法参数异常
IllegalAccessException访问某类被拒绝时抛出的异常
IndexOutOfBoundsException下标越界异常
IOException输入输出异常
NumberFormatException字符串转换为数字异常
NullPointerException空指针异常
SecurityException违背安全原则异常
SQLException操作数据库异常

error和exception有什么区别

  • error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况
  • exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况

如何看待代码中的编译时异常和运行时异常?

  • 1:使用try-catch-finally处理编译时异常,是得程序在编译时就不再报错,但是运行时仍可能报错。相当于我们使用try-catch-finally将一个编译时可能出现的异常,延迟到运行时出现。
  • 2:开发中,由于运行时异常比较常见,所以我们通常就不针对运行时异常编写try-catch-finally了。针对于编译时异常,我们说一定要考虑异常的处理。

throw 和 throws的区别是什么?

  • throw 表示抛出一个异常类的对象,生成异常对象的过程。声明在方法体内。
  • throws 属于异常处理的一种方式,声明在方法的声明处。

以下程序输入结果是什么

代码段1

class Demo {
	public static void func() {
		try {
			throw new Exception();
		} finally {
			System.out.println("B");
		}
	}

	public static void main(String[] args) {
		try {
			func();
			System.out.println("A");
		} catch (Exception e) {
			System.out.println("C");
		}
		System.out.println("D");
	}
}

//编译不通过
编译失败:
如果func放上声明了该异常

代码段2

class Demo {
    public static void main(String[] args) {
        try {
            showExce();
            System.out.println("A");
        } catch (Exception e) {
            System.out.println("B");
        } finally {
            System.out.println("C");
        }
        System.out.println("D");
    }

    public static void showExce() throws Exception {
        throw new Exception();
    }
}

输出结果为:BCD

代码段3

class Demo {
    public static void func() {
        try {
            throw new Exception();
            System.out.println("A");
        } catch (Exception e) {
            System.out.println("B");
        }
    }

    public static void main(String[] args) {
        try {
            func();
        } catch (Exception e) {
            System.out.println("C");
        }
        System.out.println("D");
    }
}

//编译失败。 因为打印“A”的输出语句执行不到。
throw单独存在,下面不要定义语句,因为执行不到

代码段4

class Exc0 extends Exception {
}

class Exc1 extends Exc0 {
}

class Demo {
    public static void main(String[] args) {
        try {
            throw new Exc1();
        } catch (Exception e) {
            System.out.println("Exception");
        } catch (Exc0 e) {
            System.out.println("Exc0");
        }
    }
}

编译不通过!
**多个catch时,父类的catch要放在下面**

代码段5

class Test {
    public static String output = "";

    public static void foo(int i) {
        try {
            if (i == 1)
                throw new Exception();
            output += "1";
        } catch (Exception e) {
            output += "2";
            // return;
        } finally {
            output += "3";
        }
        output += "4";
    }

    public static void main(String args[]) {
        foo(0);
        System.out.println(output);//①
        foo(1);
        System.out.println(output);//②
    }
}

①//134

②//134234

代码段6

public class ReturnExceptionDemo {
    static void methodA() {
        try {
            System.out.println("进入方法A");
            throw new RuntimeException("制造异常");
        } finally {
            System.out.println("用A方法的finally");
        }
    }

    static int methodB() {
        try {
            System.out.println("进入方法B");
           
            return 1;
        } catch (Exception e) {
            return 3;
        } finally {
            System.out.println("调用B方法的finally");           
        }
    }

    public static void main(String[] args) {
        try {
            methodA();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        int i = methodB();
        System.out.println(i);
    }
}

进入方法A
用A方法的finally
制造异常
进入方法B
调用B方法的finally

** 代码段7**

public static void main(String[]args){
        int test=test(3,5);
        System.out.println(test);
        }

public static int test(int x,int y){
        int result=x;
        try{
        if(x<0||y<0){
        return 0;
        }
        result=x+y;
        return result;
        }finally{
        result=x-y;
        }
        }

输出结果为:8

java中有几种方法可以实现一个线程(jdk5.0之前)?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

  • 有两种实现方法,分别是继承Thread类与实现Runnable接口。
  • 用synchronized关键字修饰同步方法,反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。
  • suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,
    指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

sleep() 和 wait() 有什么区别?

  • sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
  • wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

同步和异步有何异同,在什么情况下分别使用他们?举例说明

  • 如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
  • 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

启动一个线程是用run()还是start()?

  • 启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法就是正常的对象调用方法的执行,并不是使用分线程来执行的。

当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

不能,一个对象的一个synchronized方法只能由一个线程访问

请说出你所知道的线程同步的方法

  • wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
  • sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
  • notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
  • notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么?

  • 多线程有两种实现方法,分别是继承Thread类与实现Runnable接口
  • 同步的实现方面有两种,分别是synchronized,wait与notify

线程的基本概念、线程的基本状态以及状态之间的关系

  • 线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身
  • Java中的线程有四种状态分别是:创建、就绪、运行、阻塞、结束

简述synchronized和java.util.concurrent.locks.Lock的异同 ?

  • 相同点:Lock能完成synchronized所实现的所有功能
  • 不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。

Java为什么要引入线程机制,线程、程序、进程之间的关系是怎样的。

  • 线程可以彼此独立的执行,它是一种实现并发机制的有效手段,可以同时使用多个线程来完成不同的任务,并且一般用户在使用多线程时并不考虑底层处理的细节。
  • 程序是一段静态的代码,是软件执行的蓝本。进程是程序的一次动态执行过程,即是处于运行过程中的程序。
  • 线程是比进程更小的程序执行单位,一个进程可以启动多个线程同时运行,不同线程之间可以共享相同的内存区域和数据。多线程程序是运行时间后嗣可能出现在一个进程之内的、有一个以上线程同时运行的情况的程序。

Runnable接口包括哪些抽象方法?Thread类有哪些主要域和方法?

  • Runnable接口中仅有run()抽象方法。
  • Thread类主要域有:MAX_PRIORITY,MIN_PRIORITY,NORM_PRIORITY。
  • 主要方法有start(),run(),sleep(),currentThread(),setPriority(),getPriority(),join()等。

创建线程有哪两种方式(jdk5.0之前)?试写出每种的具体的流程。比较两种创建方式的不同,哪个更优。

  • 继承Thread类

    ​ 1) 定义类继承Thread类。

    ​ 2) 覆盖Thread类中的run方法。

    ​ 3) 创建Thread子类对象,即创建了线程对象。

    ​ 4) 调用线程对象start方法:启动线程,调用run方法。

  • 实现Runnable接口

    ​ 1)定义类,实现Runnable接口。

    ​ 2)覆盖Runnable接口中的run方法。

    ​ 3)通过Thread类建立线程对象。

    ​ 4)将Runnable接口的子类对象作为实际参数传递给Thread类的构造方法中。

    ​ 5)调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。

  • 区别

    ​ 继承Thread: 线程代码存放Thread子类run方法中。

    ​ 实现Runnable:线程代码存在接口的子类的run方法。

  • 实现方法的好处

    ​ 1)避免了单继承的局限性

    ​ 2)多个线程可以共享同一个接口子类的对象,非常适合多个相同线程来处理同一份资源。

Collection 和 Collections的区别

  • Collection是集合类的上级接口,继承于他的接口主要有Set 和List
  • Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作

Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别

  • Set里的元素是不能重复的,用equals()方法判读两个Set是否相等
  • equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值

List, Set, Map是否继承自Collection接口

  • List,Set是,Map不是

两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对

  • 不对,有相同的hash code

说出ArrayList,Vector, LinkedList的存储性能和特性

  • ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢
  • Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快

HashMap和Hashtable的区别

  • HashMap与Hashtable都实现了Map接口。
  • 由于HashMap的非线程安全性,效率上可能高于Hashtable。Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。
    HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
  • HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
  • Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
  • Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

ArrayList和Vector的区别

  • 就ArrayList与Vector主要从二方面来说:
    1. 同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的
    2. 数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值