java基础面试

本文全面解析了Java中的核心概念和技术,包括集合类如Set、List、Map的特点与应用场景,方法的重载与重写区别,抽象类与接口的区别,以及常见容器类的性能对比等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

InterviewQuestions:面试题:

Set: HashSet,TreeSet 无序不重复

List :ArrayList , LinkedList,  Vector ,有序重复

Map: HashMap, Hashtable  键无序不重复 值可以重复
一、重载和重写的区别

一、定义不同

方法的重载:在同一个类中方法名相同,参数列表(个数、类型)不同。不能重载只有返回值类型不同的方法,和返回值无关

重写(override,在有继承关系的类中的方法名,参数,返回值和父类一样,但是方法体的内容不同

  可以在方法上加@Override验证此方法是不是重写了父类的方法

二、规则上的不同:

1、重载的规则:

①必须具有不同的参数列表。

②可以有不同的访问修饰符。

③可以抛出不同的异常。

2、重写方法的规则:

①参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

②返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

③访问修饰符的限制一定要大于被重写方法的访问修饰符。

④重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。

三、类的关系上的区别:

重写是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。

二、抽象类和普通类的区别

1.抽象类不能被实例化。

2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。

3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体

4.含有抽象方法的类必须申明为抽象类

5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。

三、抽象类和接口的区别

接口是对抽象类的进一步抽象

接口就是某个事物对外提供的一些功能的声明,通过interface关键字完成

注:

1、接口中所有的属性默认为:public static final。。。;

2、接口中所有的方法默认为:public abstract。。。;

3、接口不需要像类一样被继承,而是用implements去实现,类和接口的关系叫实现。

1、实现方法:

抽象类中可以有已经实现的方法,因为存在抽象方法,所以必须是抽象类

接口中只能包含抽象方法,抽象方法是没有被实现的,只能被重写

2、子类使用的关键词不一样

抽象类使用extends来继承,抽象类就是用来被继承的,所包含的抽象方法也需要被重写

接口使用implement关键字来实现,提供接口中所有声明方法的实现

(抽象类是将梦想传给家族,一代一代去完成。那么接口就是掌门人找大师兄来完成帮派的鸿星伟业,这时候就只有一次希望,要么有能力就实现,没能力就不要接。)

3、是否有构造器(构造函数)

抽象类是类,所有类的所有特性,是不能被实例化,但可以有构造器

接口是不能有构造器的,是所包含的所有抽象方法的集合

4、修饰符

抽象类可以有public、protected、default这些修饰符

接口只有一个修饰符public

5、运行速度

抽象方法快

接口运行慢,需要时间寻找在类中实现的方法

6、继承实现

抽象类中一个子类只能继承一个父类但是可以有多个接口

四、 static类和final类

final

1.final可以修饰类,被final修饰的类称为终态类(不能有子类或者不能被继承)

2.final可以修饰属性,被final修饰的属性不能被修改,final也可以修饰局部变量,其值不能被修改

3.final修饰方法

被final修饰的类不能被继承,修饰的属性的属性值不能被改变,修饰的方法不能被重写

Static

  1. 可以修饰属性,被static修饰的属性称为静态属性可以用类名直接调用
  2. static可以修饰方法,被static修饰的方法称为静态方法,可以用类名直接调用
  3. 注意问题:静态的只能访问静态的,非静态的谁都可以访问

静态方法可以访问静态属性和静态方法,不能访问非静态属性和非静态方法

非静态方法既可以访问静态方法和静态属性也可以访问非静态方法和非静态属性

五、abstract类

用abstract修饰的类叫抽象类

1、抽象类不能有对象,抽象类不能实例化,不能new

2abstract修饰的方法为抽象方法,这种方法不能有方法体(什么内容都没有)

3、抽象类不能有对象,不能new对象

4、有抽象方法的一定是抽象类,抽象类中不一定有抽象方法

5、抽象类型中的抽象方法必须在子类中被重写

六、ArrayList 与 LinkedList 的区别

1.ArrayList(数组列表)底层是一个数组 查找速度快(空间连续)增加和删除速度慢,空间占用比较严重

2.LinkedList(链表)底层是一个双向链表  查找速度慢 (空间不连续) (断链进行增删)增加和删除速度快空间占用不严重。

List<泛型> list = new ArrayList<泛型>();

List<泛型> list = newLinkedList<泛型>()

ArrayList与Vector区别
1.ArrayList出现在jdk1.2  Vector出现在jdk1.0
 2.ArrayList效率高 Vector效率低
 3.ArrayList线程不安全 Vector线程安全
 4. ArrayList扩容是原来的1.5倍 Vector扩容是原来的2倍
 ArrayList与Vector相同点
 底层都是数组。

七、HashMap与HashSet 区别

1. HashSet底层是HashMap,HashSet只使用了HashMap的键,HashMap的值使用的是Object对象。初始容量为16,负载因子0.75(大于百分之七十五开始扩容)

2. HashMap底层是数组+链表(jdk8以后 如果链表的长度大于8会自动转换成红黑树)(左小右大)的目的是为了增加查找链表的速度

八、Hashtable<K,V>与HashMap<K,V>区别

1.父类不同

Hashtable继承 extended by java.util.Dictionary<K,V>

HashMap继承 extended by java.util.AbstractMap<K,V>

 2.出现版本不同

Hashtable 出现于jdk1.0  HashMap 出现于jdk1.2

3对于null的支持不同

Hashtable 键值对都不可以为null  HashMap键值对都可以为null

 4.效率不同

Hashtable 效率低    HashMap   效率高

5.线程安全不同

Hashtable 线程安全   HashMap   线程不安全

6.初始容量不同

Hashtable 11   HashMap  16

7.扩容速度不同

Hashtable 扩容是原来的2n+1倍  HashMap  扩容是原来的2倍

8.hashCode重写方式不同;

Hashtable 计算复杂     HashMap  计算简单

九、ArrayList与Vector区别

不同点

1.ArrayList出现在jdk1.2  Vector出现在jdk1.0

2.ArrayList效率高 Vector效率低

3.ArrayList线程不安全 Vector线程安全

4. ArrayList扩容是原来的1.5倍 Vector扩容是原来的2倍

ArrayList与Vector相同点
 底层都是数组。

七、Internet

网络协议

1、.TCP协议 传输控制协议(Transmission Control Protocol)

   面向连接的,可靠的,基于字节流的传输层通信协议

 2、UDP协议用户数据报协议(User Datagram Protocol)

   区别:

   1.TCP面向连接的; UDP面向无连接

   2. .TCP效率低; UDP高

   3.TCP可靠,传输数据不会丢失;UDP不可靠,可能会丢失数据

   4. .TCP传输数据大小没有限制; UDP传输时每个包大小一般不超过64kb

   5. .TCP传输是点对点的传输;UDP可以一对一,一对多。

   八、工具类

  特征:

  1.构造方法私有化

  2.所有方法都是静态方法 ,属性都是常量

  九、final与finally的区别

  1.final可以修饰类 ,final类不能有子类;也可以修饰方法,final方法不能被重写, final的变量的值不能被改变

  2.finally一般位于try{}catch(){}的后面,无论是否出现异常都会执行

十、以下String类代码的的运行结果

  String 引用数据类型 字符串是不可变类(LocalDate) 每次对字符串修改都会创建新的对象。

public class StringInQu {

    public static void main(String[] args) {

        String S = "1";

        String s = S+"2";

        使用字面量赋值时会在常量池中创建hello对象

        以后使用hello时会从常量池中找到该对象,并使用常量池对象内存地址

        String s1 = "hello";

        String s2 = "hello";

        System.out.println(s == S);

        System.out.println(s1 == s2);

        当使用new字符串时,会在堆内存中开辟内存空间,并s3指向该内存地址

        如果前面没有定义hello ,此时使用new 会创建两个对象。堆内存中+常量池

        如果前面已经定义了hello,此时使用new只会创建一个对象。堆内存中

        String s3 = new String("hello");

        System.out.println(s2 == s3);

        当两个字符串常量相加,当编译成class文件时会自动拼接

        当常量池中已经有hello时,将不会创建新的内存地址。

        String s4 = "hel"+"lo";

        System.out.println(s2 == s4);

        String s5 = "hel";

        String s6 = "lo";

        s5 s6 在编译期间无法确定 ,(变量) 会在堆内存创建该对象

         而s2在常量池中,所以不相等

        System.out.println(s2 == (s5+s6));false;

        System.out.println(s2.equals(s5+s6));true 比较内容

    }

}

十一、 throw与throws的区别

  1.位置不同 ,throw位于方法内部,throws位于方法的声明处

  2.后面的内容不同,throw后跟异常对象,throws后跟异常类

  3.后面的个数不同,throw后跟一个异常对象,throws后跟n个异常类。

十二、wait和sleep的区别
1.wait是Object类的方法,sleep是Thread类的方法
 2.wait只能用于同步代码块中,sleep可以位于任意方法中
 3.sleep不释放锁,wait释放锁
 4.sleep可以在指定的毫秒数内醒来,wait既可以通过毫秒数醒来,也可以通过notify被唤醒

十三、i++和i=i+1的区别

        如果i是int类型没有区别

        如果是byte,short类型,使用i++时会自动类型转换

        如果是byte,short类型,使用i = i + 1时需要手动类型转换

十四、String和String Buffer的区别

1.String 对象是不可变字符串,在程序中对字符串进行比较、查找、类型转换等操作时,使用string 对象表示字符串,提高程序执行效率。

2.String Buffer 对象是可变字符串,在程序中对字符串的内容和长度进行修改时,使用String Buffer 对象表示字符串。

3.都是引用数据类型

4.String 对象一旦被创建,就不能修改它的值.对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.String final,不能被继承,String 方法也不能被重写。    

String 类型和 String Buffer 的主要性能区别:String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。

使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

Marker Interface(标志性接口)

Serializable接口没有属性也没有方法,我们把这种接口称为Marker Interface(标志性接口)

函数式接口

:当一个接口只有一个抽象方法时

//可以通过@FunctionalInterface注解来判断是否是函数式接口

@FunctionalInterface

public interface A {

    void methodA();

}

lambda表达式

语法结构:

(参数类型1 参数名1,参数类型2 参数名2...)->{语句1;语句2;...}

如果只有一条语句时大括号可以省略

使用lambda表达式,要接口必须是函数式接口

使用情况:

1.函数式接口(函数式接口:当一个接口只有一个抽象方法时或如果接口中两个抽象方法,一个和Object类有关时)

2.Tree Set 使用Comparable作为比较器时

3.使用Runnable接口(只有一个run方法)创建线程时New thread(()->语句);

出现线程安全问题的原因:

1.多线程环境

2.多个线程要有共享数据

3.多个线程对共享数据进行修改

PreparedStatement(Statement的子接口) 和 Statement的区别

  1. Statement维护性,可读性较差 PreparedStatement 可维护性,可读性较好
  2. Statement 效率低 PreparedStatement效率高
  3. Statement安全性低 PreparedStatement安全性高

InterviewQuestions:面试题:

Set: HashSet,TreeSet 无序不重复

List :ArrayList , LinkedList,  Vector ,有序重复

Map: HashMap, Hashtable  键无序不重复 值可以重复
一、重载和重写的区别

一、定义不同

方法的重载:在同一个类中方法名相同,参数列表(个数、类型)不同。不能重载只有返回值类型不同的方法,和返回值无关

重写(override,在有继承关系的类中的方法名,参数,返回值和父类一样,但是方法体的内容不同

  可以在方法上加@Override验证此方法是不是重写了父类的方法

二、规则上的不同:

1、重载的规则:

①必须具有不同的参数列表。

②可以有不同的访问修饰符。

③可以抛出不同的异常。

2、重写方法的规则:

①参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

②返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

③访问修饰符的限制一定要大于被重写方法的访问修饰符。

④重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。

三、类的关系上的区别:

重写是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。

二、抽象类和普通类的区别

1.抽象类不能被实例化。

2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。

3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体

4.含有抽象方法的类必须申明为抽象类

5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。

三、抽象类和接口的区别

接口是对抽象类的进一步抽象

接口就是某个事物对外提供的一些功能的声明,通过interface关键字完成

注:

1、接口中所有的属性默认为:public static final。。。;

2、接口中所有的方法默认为:public abstract。。。;

3、接口不需要像类一样被继承,而是用implements去实现,类和接口的关系叫实现。

1、实现方法:

抽象类中可以有已经实现的方法,因为存在抽象方法,所以必须是抽象类

接口中只能包含抽象方法,抽象方法是没有被实现的,只能被重写

2、子类使用的关键词不一样

抽象类使用extends来继承,抽象类就是用来被继承的,所包含的抽象方法也需要被重写

接口使用implement关键字来实现,提供接口中所有声明方法的实现

(抽象类是将梦想传给家族,一代一代去完成。那么接口就是掌门人找大师兄来完成帮派的鸿星伟业,这时候就只有一次希望,要么有能力就实现,没能力就不要接。)

3、是否有构造器(构造函数)

抽象类是类,所有类的所有特性,是不能被实例化,但可以有构造器

接口是不能有构造器的,是所包含的所有抽象方法的集合

4、修饰符

抽象类可以有public、protected、default这些修饰符

接口只有一个修饰符public

5、运行速度

抽象方法快

接口运行慢,需要时间寻找在类中实现的方法

6、继承实现

抽象类中一个子类只能继承一个父类但是可以有多个接口

四、 static类和final类

final

1.final可以修饰类,被final修饰的类称为终态类(不能有子类或者不能被继承)

2.final可以修饰属性,被final修饰的属性不能被修改,final也可以修饰局部变量,其值不能被修改

3.final修饰方法

被final修饰的类不能被继承,修饰的属性的属性值不能被改变,修饰的方法不能被重写

Static

  1. 可以修饰属性,被static修饰的属性称为静态属性可以用类名直接调用
  2. static可以修饰方法,被static修饰的方法称为静态方法,可以用类名直接调用
  3. 注意问题:静态的只能访问静态的,非静态的谁都可以访问

静态方法可以访问静态属性和静态方法,不能访问非静态属性和非静态方法

非静态方法既可以访问静态方法和静态属性也可以访问非静态方法和非静态属性

五、abstract类

用abstract修饰的类叫抽象类

1、抽象类不能有对象,抽象类不能实例化,不能new

2abstract修饰的方法为抽象方法,这种方法不能有方法体(什么内容都没有)

3、抽象类不能有对象,不能new对象

4、有抽象方法的一定是抽象类,抽象类中不一定有抽象方法

5、抽象类型中的抽象方法必须在子类中被重写

六、ArrayList 与 LinkedList 的区别

1.ArrayList(数组列表)底层是一个数组 查找速度快(空间连续)增加和删除速度慢,空间占用比较严重

2.LinkedList(链表)底层是一个双向链表  查找速度慢 (空间不连续) (断链进行增删)增加和删除速度快空间占用不严重。

List<泛型> list = new ArrayList<泛型>();

List<泛型> list = newLinkedList<泛型>()

ArrayList与Vector区别
1.ArrayList出现在jdk1.2  Vector出现在jdk1.0
 2.ArrayList效率高 Vector效率低
 3.ArrayList线程不安全 Vector线程安全
 4. ArrayList扩容是原来的1.5倍 Vector扩容是原来的2倍
 ArrayList与Vector相同点
 底层都是数组。

七、HashMap与HashSet 区别

1. HashSet底层是HashMap,HashSet只使用了HashMap的键,HashMap的值使用的是Object对象。初始容量为16,负载因子0.75(大于百分之七十五开始扩容)

2. HashMap底层是数组+链表(jdk8以后 如果链表的长度大于8会自动转换成红黑树)(左小右大)的目的是为了增加查找链表的速度

八、Hashtable<K,V>与HashMap<K,V>区别

1.父类不同

Hashtable继承 extended by java.util.Dictionary<K,V>

HashMap继承 extended by java.util.AbstractMap<K,V>

 2.出现版本不同

Hashtable 出现于jdk1.0  HashMap 出现于jdk1.2

3对于null的支持不同

Hashtable 键值对都不可以为null  HashMap键值对都可以为null

 4.效率不同

Hashtable 效率低    HashMap   效率高

5.线程安全不同

Hashtable 线程安全   HashMap   线程不安全

6.初始容量不同

Hashtable 11   HashMap  16

7.扩容速度不同

Hashtable 扩容是原来的2n+1倍  HashMap  扩容是原来的2倍

8.hashCode重写方式不同;

Hashtable 计算复杂     HashMap  计算简单

九、ArrayList与Vector区别

不同点

1.ArrayList出现在jdk1.2  Vector出现在jdk1.0

2.ArrayList效率高 Vector效率低

3.ArrayList线程不安全 Vector线程安全

4. ArrayList扩容是原来的1.5倍 Vector扩容是原来的2倍

ArrayList与Vector相同点
 底层都是数组。

七、Internet

网络协议

1、.TCP协议 传输控制协议(Transmission Control Protocol)

   面向连接的,可靠的,基于字节流的传输层通信协议

 2、UDP协议用户数据报协议(User Datagram Protocol)

   区别:

   1.TCP面向连接的; UDP面向无连接

   2. .TCP效率低; UDP高

   3.TCP可靠,传输数据不会丢失;UDP不可靠,可能会丢失数据

   4. .TCP传输数据大小没有限制; UDP传输时每个包大小一般不超过64kb

   5. .TCP传输是点对点的传输;UDP可以一对一,一对多。

   八、工具类

  特征:

  1.构造方法私有化

  2.所有方法都是静态方法 ,属性都是常量

  九、final与finally的区别

  1.final可以修饰类 ,final类不能有子类;也可以修饰方法,final方法不能被重写, final的变量的值不能被改变

  2.finally一般位于try{}catch(){}的后面,无论是否出现异常都会执行

十、以下String类代码的的运行结果

  String 引用数据类型 字符串是不可变类(LocalDate) 每次对字符串修改都会创建新的对象。

public class StringInQu {

    public static void main(String[] args) {

        String S = "1";

        String s = S+"2";

        使用字面量赋值时会在常量池中创建hello对象

        以后使用hello时会从常量池中找到该对象,并使用常量池对象内存地址

        String s1 = "hello";

        String s2 = "hello";

        System.out.println(s == S);

        System.out.println(s1 == s2);

        当使用new字符串时,会在堆内存中开辟内存空间,并s3指向该内存地址

        如果前面没有定义hello ,此时使用new 会创建两个对象。堆内存中+常量池

        如果前面已经定义了hello,此时使用new只会创建一个对象。堆内存中

        String s3 = new String("hello");

        System.out.println(s2 == s3);

        当两个字符串常量相加,当编译成class文件时会自动拼接

        当常量池中已经有hello时,将不会创建新的内存地址。

        String s4 = "hel"+"lo";

        System.out.println(s2 == s4);

        String s5 = "hel";

        String s6 = "lo";

        s5 s6 在编译期间无法确定 ,(变量) 会在堆内存创建该对象

         而s2在常量池中,所以不相等

        System.out.println(s2 == (s5+s6));false;

        System.out.println(s2.equals(s5+s6));true 比较内容

    }

}

十一、 throw与throws的区别

  1.位置不同 ,throw位于方法内部,throws位于方法的声明处

  2.后面的内容不同,throw后跟异常对象,throws后跟异常类

  3.后面的个数不同,throw后跟一个异常对象,throws后跟n个异常类。

十二、wait和sleep的区别
1.wait是Object类的方法,sleep是Thread类的方法
 2.wait只能用于同步代码块中,sleep可以位于任意方法中
 3.sleep不释放锁,wait释放锁
 4.sleep可以在指定的毫秒数内醒来,wait既可以通过毫秒数醒来,也可以通过notify被唤醒

十三、i++和i=i+1的区别

        如果i是int类型没有区别

        如果是byte,short类型,使用i++时会自动类型转换

        如果是byte,short类型,使用i = i + 1时需要手动类型转换

十四、String和String Buffer的区别

1.String 对象是不可变字符串,在程序中对字符串进行比较、查找、类型转换等操作时,使用string 对象表示字符串,提高程序执行效率。

2.String Buffer 对象是可变字符串,在程序中对字符串的内容和长度进行修改时,使用String Buffer 对象表示字符串。

3.都是引用数据类型

4.String 对象一旦被创建,就不能修改它的值.对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.String final,不能被继承,String 方法也不能被重写。    

String 类型和 String Buffer 的主要性能区别:String 是不可变的对象, 因此在每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。

使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

Marker Interface(标志性接口)

Serializable接口没有属性也没有方法,我们把这种接口称为Marker Interface(标志性接口)

函数式接口

:当一个接口只有一个抽象方法时

//可以通过@FunctionalInterface注解来判断是否是函数式接口

@FunctionalInterface

public interface A {

    void methodA();

}

lambda表达式

语法结构:

(参数类型1 参数名1,参数类型2 参数名2...)->{语句1;语句2;...}

如果只有一条语句时大括号可以省略

使用lambda表达式,要接口必须是函数式接口

使用情况:

1.函数式接口(函数式接口:当一个接口只有一个抽象方法时或如果接口中两个抽象方法,一个和Object类有关时)

2.Tree Set 使用Comparable作为比较器时

3.使用Runnable接口(只有一个run方法)创建线程时New thread(()->语句);

出现线程安全问题的原因:

1.多线程环境

2.多个线程要有共享数据

3.多个线程对共享数据进行修改

PreparedStatement(Statement的子接口) 和 Statement的区别

  1. Statement维护性,可读性较差 PreparedStatement 可维护性,可读性较好
  2. Statement 效率低 PreparedStatement效率高
  3. Statement安全性低 PreparedStatement安全性高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值