Java面试题(一)基础系列

一.java 基础

1.抽象类和接口

  • 接口是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
  • 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

2.封装,继承,多态

  • 封装:抽象性函式接口的实现细节部分包装、隐藏起来的方法。
  • 继承:继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
  • 多态:多态是同一个行为具有多个不同表现形式或形态的能力。

3.重写和重载

  • 重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
  • 重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。最常用的就是构造器重载

4.java基本数据类型

类型取值范围默认值大小包装类
byte-2^7 ~ 2^7-1(byte)01字节8位Byte
short-2^15 ~ 2^15 - 1(short)02字节16位整数Short
int-2^31 ~ 2^31 - 104字节32位整数Integer
long-2^63 ~ 2^63 -10L8字节64位整数Long
float-2^128 ~ 2^1280.0f4字节32位浮点数Float
double-2^1024 ~ 2^10240.0d8字节64位浮点数Double
booleantrue ~ falsefalse1字节8位Boolean
char\u0000(0) ~ \uffff(65,535)02字节16位Unicode字符Character

5.拆箱装箱

在JDK1.5以后,基础类型和包装类可以自动转换,称为自动装箱和拆箱。

自动装箱就是自动将基本数据类型转换为包装器类型;
自动拆箱就是自动将包装器类型转换为基本数据类型。
自动装箱和拆箱都是在编译阶段就完成的。
自动装箱的时候,java编译器会默认调用valueOf进行装箱,拆箱时会调用**Value方法。

//自动装箱,相当于调用了Integer.valueOf()方法
Integer a = 22;
//自动拆箱,相当于调用了a.intValue()方法
int b = a;

6.包装类缓存

部分包装类提供了对象的缓存,实现方式是在类初始化时提前创建好会频繁使用的包装类对象,当需要使用某个包装类的对象时,如果该对象包装的值在缓存的范围内,就返回缓存的对象,否则就创建新的对象并返回。

System.out.println(Integer.valueOf("1000")==Integer.valueOf("1000"));//false
System.out.println(Integer.valueOf("128")==Integer.valueOf("128"));//false
System.out.println(Integer.valueOf("127")==Integer.valueOf("127"));//true
System.out.println(Integer.valueOf("-128")==Integer.valueOf("-128"));//true

我们来看看Integer.valueOf()的源码

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

在-128~127之间会返回缓存对象,所以比较的内容地址是一样的,如果超过了这个范围就会创建一个新对象,所以比较就会2个不一样的内存地址

7.类变量,实例变量,局部变量

  • 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外;
  • 实例变量声明在一个类中,但在方法、构造方法和语句块之外;
  • 局部变量声明在方法、构造方法或者语句块中;
public class Variable{
	// 类变量
    static int allClicks=0; 
    // 实例变量
    String str="hello world";

    public void method(){
    	// 局部变量
		int i =0;
    }
}

8.访问修饰符

修饰符当前类同一包内子孙类(同一包)子孙类(不同包)其他包
publicYYYYY
protectedYYYYN
defaultYYYNN
privateYNNNN

9.非访问修饰符

  • static修饰符,静态变量或方法
  • final修饰符,被 final 修饰的实例变量必须显式指定初始值
  • abstract修饰符,抽象类和方法
  • synchronized修饰符,声明的方法同一时间只能被一个线程访问
  • transient修饰符,被transient关键字修饰的变量不再能被序列化
  • volatile修饰符,volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值

10.JDK 和 JRE 的区别

  • JDK:Java Development Kit 的简称,Java 开发工具包,提供了 Java 的开发环境和运行环境。
  • JRE:Java Runtime Environment 的简称,Java 运行环境,为 Java 的运行提供了所需环境。

11.== 和 equals 的区别

== 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

12.final, finally, finalize 的区别

  • final修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载。

  • finally在异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。

  • finalize方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。

13.JDBC的流程

//加载JDBC驱动程序
Class.forName("com.mysql.jdbc.Driver");
//创建连接
Connection conn = DriverManager.getConnection(url,username,password);
//创建Statement
Statement st = conn.createStatement();
//执行SQL
ResultSet rs = st.executeQuery("select * from user");

List<User> userList = new ArrayList<>();
//处理结果
while (rs.next()) {
   User user = new User();
   user.setId(rs.getString("id"));
   user.setName(rs.getString("name"));
   userList.add(user);
}
//异常捕获
//关闭资源
rs.close();
st.close();
conn.close();

14.&和&&的区别

  • &&具有短路的功能,而&不具备短路功能。

  • 当&运算符两边的表达式的结果都为true时,整个运算结果才为true。而&&运算符第一个表达式为false时,则结果为false,不再计算第二个表达式。

  • &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位,例如:0x31 & 0x0f的结果为0x01。

15.下列代码分别输出多少

long a = Math.round(11.5);
long b = Math.round(-11.5);
System.out.print("a=" + a);
System.out.print("b=" + b);

输出:a=12 ;b=-11

16.switch支持哪些类型

  • 基本数据类型:byte, short, char, int

  • 包装数据类型:Byte, Short, Character, Integer

  • 枚举类型:Enum

  • 字符串类型:String(JDK1.7之后) 开始支持

  • 不支持boolean和double型

17.事务的ACID是什么

  • 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
  • 一致性(Consistent):事务结束后系统状态是一致的;
  • 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
  • 持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

二.java 集合

1.Vector 与 Array 的区别

  • ArrayList在内存不够时默认是扩展50% + 1个,Vector是默认扩展1倍。

  • Vector属于线程安全级别的,但是大多数情况下不使用Vector,因为线程安全需要更大的系统开销。

2.HashMap 与 Hashtable 的区别

  • Hashtable继承Dictonary类, HashMap继承自abstractMap

  • HashMap允许空的键值对, 但最多只有一个空对象,而HashTable不允许。

  • HashTable同步,而HashMap非同步,效率上比HashTable要高

3.ArrayList与 LinkedList 的区别

  • ArrrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。LinkedList是双向链表
  • 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
  • LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

4.List 和 Set 的区别

  • List,Set都是继承自Collection接口

  • List:元素有放入顺序,元素可重复

  • Set:元素无放入顺序,元素不可重复,重复元素会覆盖掉

  • Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。

  • List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

5.Comparator 与Comparable的区别

Comparable 接口用于定义对象的自然顺序,是排序接口,而 comparator 通常用于定义用户定制的顺序,是比较接口。我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

6.Collection与Collections的区别

  • Collection是Java集合框架中的基本接口;

  • Collections是Java集合框架提供的一个工具类,其中包含了大量用于操作或返回集合的静态方法。

三.java 反射

1.反射的主要功能

  • 确定一个对象的类
  • 取出类的modifiers,数据成员,方法,构造器,和超类.
  • 找出某个接口里定义的常量和方法说明.
  • 创建一个类实例,这个实例在运行时刻才有名字(运行时间才生成的对象).
  • 取得和设定对象数据成员的值,如果数据成员名是运行时刻确定的也能做到.
  • 在运行时刻调用动态对象的方法.
  • 创建数组,数组大小和类型在运行时刻才确定,也能更改数组成员的值.

2.哪些地方用到了反射

  • spring 的 ioc/di 也是反射
  • javaBean和jsp之间调用也是反射
  • struts的 FormBean 和页面之间也是通过反射调用
  • JDBC 的 classForName()也是反射
  • hibernate的 find(Class clazz) 也是反射

3.Class.forName 和 ClassLoader的区别

  • class.forName()除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。当然还可以指定是否执行静态块
  • classLoader只干一件事情,就是将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。
  • 这里可以去看看JDBC 加载MySQL的时候为什么用class.forName()

四.java String

1.String,StringBuilder,StringBuffer的区别

  • String:不可变字符串,适合少量字符使用

  • StringBuffer:可变字符串、效率低、线程安全,适合多线程操作大量自字符

  • StringBuilder:可变字符序列、效率高、线程不安全,适合单线程操作大量字符

2.写出10个String类中常用方法

  • indexOf():返回指定字符的索引。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。

五.java io

1.java中IO分哪几种,有什么区别

  • 按功能来分:输入流(input)、输出流(output)。

  • 按类型来分:字节流和字符流。

  • 字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

2.BIO、NIO、AIO 的区别

  • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
  • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

珍妮玛•黛金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值