Java面试复习

目录

Java语言基础部分 

JVM?JDK?JRE?

Java语言的特点

Java语言的特性

基本数据类型

byte常用在什么地方

数据输入

常用Math方法(静态)

switch语句

跳转语句 break和continue

如何在main()方法之前输出”Hello World”?

java中的 clone()方法作用?

浅复制和深复制的区别?

Java反射机制

什么是String不可变

参数传递方式:值传递和引用传递

“==” “equals” “hashCode”的区别?

为什么集合类没有实现Cloneable和Serializable接口?

Iterator和ListIterator的区别

什么是类?继承?多态?抽象类?接口?内嵌类?

代码的执行顺序

抽象类和接口的区别

使用super注意什么?

数据类型转换规则

String、StringBuffer、StringBuilder区别

StringBuffer 的扩容机制

数组

String常用方法

Date类应用

finally块中的代码什么时候执行?

捕获异常的顺序

异常分类

多线程

你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

10个线程和2个线程的同步代码,哪个更容易写?

IO流

Java集合 

常用集合的分类:

HashTable和HashMap的比较

List和set的区别

ArrayList、LinkedList、Vector的区别

Map的主要方法

JDBC技术应用

JDBC连接过程


持续ing.....

Java语言基础部分 

JVM?JDK?JRE?

JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心。

JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。

JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。

Java语言的特点

面向对象

跨平台解释执行,一次编译到处执行

健壮性和安全性:编译运行过程中提示错误

支持多线程

Java语言的特性

封装

继承

多态:方法重载、方法覆盖

抽象

基本数据类型

byte:8位,最大存储数据量是255,存放的数据范围是-128~127之间。

char:16位,存储Unicode码,用单引号赋值。

short:16位,最大数据存储量是65536,数据范围是-32768~32767之间。

int:32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正 的2的31次方减1。

long:64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正 的2的63次方减1。

float:32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F。

double:64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加。

boolean:只有true和false两个取值。

byte常用在什么地方

读取文件时(如图片,声音,可执行文件)需要用字节数组来保存文件的内容

int n = 0;

        try {

            FileInputStream fis = new FileInputStream("f:\\files\\1.txt");

            FileOutputStream fos = new FileOutputStream("f:\\files\\copy.txt");

            byte[] bs = new byte[1024*1024];

            while ((n = fis.read(bs)) != -1) {

fos.write(bs,0,n);

}

            fis.close();fos.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

 

数据输入

1.BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

String str[] = bf.readLine().split(" ");//读取一行输入用“ ”分割开。

2.Scanner sc = new Scanner(System.in);

常用Math方法(静态)

int abs(int i) 求绝对值

int max(int i, int j)

double ceil(double d) 向上取整

double floor(double d) 向下取整

double sqrt(double d) 开平方

int round(float f) 靠近 f 的整数

double.random() 返回[0,1)之间的一个随机数

switch语句

switch( x ){

case 0:

case 1:

...

}

跳转语句 break和continue

1.Break:跳出当前循环体

2跳出多重循环:

out:

for(...){

for(...){

break out;

}

}

3.continue: 终止此次循环,继续下一次,不跳出循环体

如何在main()方法之前输出Hello World

用 static 块输出

java中的 clone()方法作用?

复制对象,修改新的对象原对象不变

浅复制和深复制的区别?

对于基本类型来说一样,对于引用类型才有区别

浅复制只是复制了引用,不复制引用所指向的对象

深复制即复制引用,也复制指向的对象

Java反射机制

得到一个对象的类,可以获取类的方法和属性的一种机制;运行时创建对象,运行时调用对象的方法

常用方法:

//getMethods方法获得所有public的方法,包括继承而来

    Method[] ms = c.getMethods();

//getDeclaredMethods是获取该类自己的声明的方法

    Method[] ms = c.getMethods();

//获取类中属性   

Field[] fs = c.getDeclaredFields();

Constructor[] cs = c.getConstructors();

获取类:

  1. Class.forName(“包.类名”);
  2. 类名.Class;
  3. 实例.getClass();

创建对象的方式:

  1. new语句实例化对象
  2. 反射机制创建对象
  3. Clone方法创建对象
  4. 反序列方法创建对象 

 

什么是String不可变

String s = “hello”;

s = “word”;

String 的引用对象 s 指向新的内存空间(“word”的空间)了,hello没有变还在原来的地方。

参数传递方式:值传递和引用传递

public class Temp {

public static void m(StringBuffer s, int i) {

s.append("world");

i = 8;

}

public static void main(String[] args) {

StringBuffer s = new StringBuffer("Hello");

int i = 1;

m(s,i);

System.out.println("s="+s+"\n"+"i="+i);

}

}

运行结果:

s=Helloworld  

i=1

可见引用类型的实例 s 中形参改变实参,而基本类型 i 实参没有被改变

== equals hashCode的区别?

== 比较的是引用的值(地址)

equals 比较的是引用指向的堆内存中的值(需要重写,默认为 ==,String已经被重写)

hashCode

如果俩个对象equals相同,那么hashCode也相同

如果俩个对象的hashCode不相同,那么equals不相同

为什么集合类没有实现Cloneable和Serializable接口?

克隆(cloning)或者序列化(serialization)的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现类来决定如何被克隆或者序列化

Iterator和ListIterator的区别

1.ListIterator只能用于List,Iterator用于List和Set

2.Iterator容易引起并发修改异常问题,而ListIterator可以避免线程安全问题的发生,因为其有内置的add()等修改集合的方法。

3. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

4. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

什么是类?继承?多态?抽象类?接口?内嵌类?

类:具有相同属性和行为的集合

继承:子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或   子类从父类继承方法,使得子类具有父类相同的行为。

多态同一个行为具有多个不同表现形式或形态的能力。

多态就是同一个接口,使用不同的实例而执行不同操作

多态存在的三个必要条件:

继承、重写、父类引用指向子类对象

多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处   理。

多态实现机制:覆盖、重载

抽象类:在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并 不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘 一个具体的对象,这样的类就是抽象类。(拥有抽象方法的类)

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方 法和构造方法的访问方式和普通类一样。

由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为 这个原因,通常在设计阶段决定要不要设计抽象类。

1) 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编 译无法通过。只有抽象类的非抽象子类可以创建对象。

2) 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

3) 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实 现也 就是方法的具体功能。

4) 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

5) 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是 抽象类。

 

接口:在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以 interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法

1)接口中的方法会被隐式的指定为 public abstract(只能是 public abstract, 其他修饰符都会报错)。

2)接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量

3)接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的 方法

代码的执行顺序

父类静态变量

父类静态块

子类静态变量

子类静态块

父类非静态变量

父类非静态代码块

父类构造方法

子类非静态变量

子类非静态代码块

子类构造方法

抽象类和接口的区别

  1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行(java8之前)。

2) 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的,而且必须赋初值;抽象类里方法可以是各种的,接口里必须是public abstract。

3) 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。

4) 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

使用super注意什么?

super()要放在方法里的最前面

数据类型转换规则

满足

byte->short->int->long->float->double

char -> int

也即 低精度-->高精度 不需要强制转换,反之需要

String、StringBuffer、StringBuilder区别

String不可变,效率低,赋值、构造方法方法进行实例化

StringBuffer可变,效率较高,安全,同步,适用于单/多线程,构造方法方法进行 实例化

StringBuilder可变,效率高于StringBuffer,不安全,异步,适用于单线程,构造方 法方法进行实例化

注:String类型修改时,创建一个StringBuilder,调用append()方法,最后调用 StringBuilder的toString()方法把结果返回

示例:

String s = “Hello”;

s += “World”;

以上代码等价下述代码:

StringBuilder sb = new StringBulider(s);

sb.append(“World”);

可见,如果经常改变字符串内容的话,会产生临时对象和附加操作

所以说,单线程下使用StringBuilder效率更高

StringBuffer 的扩容机制

空构造默认是16,字符串构造是字符串长度+16
扩容:新容量= 旧容量*2+2 ,  if 判断一下 容量如果不够,直接扩充到需要的容量大小。

数组

二维数组创建时列号可以不同,如下:

int arr[][] = new int {{1,2},{3,4,5}}

String常用方法

 

Date类应用

 

finally块中的代码什么时候执行?

在return语句之前执行而且一定会执行(进入到try块后)。如果try{}或者catch{}和finally{}中都有return,那么finally{}中的return会覆盖其他的return,最终会执行finally{}中的return

(1).finally块不会执行的情况:

1.未进入到try块就出现异常

2.在try块中强制退出时,如:System.exit(0);

(2).try中返回的变量,在finally块中对其操作时,对基本变量没影响,对引用变量有影 响

捕获异常的顺序

先捕获子类异常再捕获基类异常,否则子类异常将不会执行

异常分类

Throwable 最高层

|____Error 编译时错误

|____Exception 运行时异常

 

 

Throwable有两个子类,Error和Exception。其中Error是错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。Exception,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。

 

 

  • 多线程

你是如何调用 wait()方法的?使用 if 块还是循环?为什么?

if可能出现假唤醒,应该用while(condition)。因为当wait这步被唤醒时,很可能condition已经不满足了,所以还需要判断condition。

10个线程和2个线程的同步代码,哪个更容易写?

从写代码的角度来说,两者的复杂度是相同的,因为同步代码与线程数量是相互独立的。但是同步策略的选择依赖于线程的数量,因为越多的线程意味着更大的竞争,所以你需要利用同步技术,如锁分离,这要求更复杂的代码和专业知识。

  • IO流

  • Java集合 

常用集合的分类:

Collection 接口的接口 对象的集合(单列集合)

├——-List 接口:元素按进入先后有序保存,可重复

│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全

│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全

│—————--└ Vector 接口实现类 数组, 同步, 线程安全

│ ———————-└ Stack 是Vector类的实现类

└——-Set 接口: 仅接收一次,不可重复,并做内部排序

├—————-HashSet 使用hash表(数组)存储元素,HashMap实现

│————————└ LinkedHashSet 链表维护元素的插入次序

└ —————-TreeSet 底层实现为二叉树,元素排好序

Map 接口 键值对的集合 (双列集合)

├———Hashtable 接口实现类, 同步, 线程安全(key和val不能为null)

├———HashMap 接口实现类 ,异步, 线程不安全(一个key为null,val可以多个为null)

│—————–├ LinkedHashMap 双向链表和哈希表实现

│—————–└ WeakHashMap

├ ——–TreeMap 红黑树对所有的key进行排序

└———IdentifyHashMap

HashTable和HashMap的比较

 

 

List和set的区别

 

ArrayList、LinkedList、Vector的区别

 

Map的主要方法

 

JDBC技术应用

JDBC连接过程

Try{

//加载数据库驱动,注册到驱动管理器

Class.forName("com.mysql.jdbc.Driver ");

String oraURL= "jdbc:mysql://localhost:3306/db";

//获取Connection对象

Connection con=DriverManager.getConnection(oraURL, username,password);

Statement statement =con.createStatement();

String query = "SELECT name, pwd FROM sometable";

ResultSet resultSet= statement.executeQuery(query);

while(resultSet.next()){

name =resultSet.getString(1);

phone =resultSet.getString(2);

System.out.println(name+","+phone);

}catch(SQLException e){

se.printStackTrace();

 } finally{ // 关闭资源

    try{
        if(resultSet != null)
            resultSet.close();
        if(stmt!=null) 
            stmt.close(); 
        if(conn!=null)
            conn.close();
    }catch(SQLException e){
        e.printStackTrace();
     }

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值