熬夜整理了一份java基础面试题,希望大家支持,如果文中有错误希望大家指正;
知识追寻者(Inheriting the spirit of open source, Spreading technology knowledge;)
优点: 性能比面向对象高 ,因为类调用时需要实例化,开销比较大,比较消耗 资源
应用场景:单片机、嵌入式开发、Linux/Unix ;
缺点:没有面向对象易维护、易复用、易扩展
优点:因为面向对象有封装、继承、多态性的特 性,可以设计出低耦合的系统,故易维护、易复用、易扩展;
应用场景:网页开发,后台开发等;
缺点:性能比面向过程低
多态实现形式:
重写:子类对父类方法的重写;
覆盖:实现接口,并覆盖方法;
抽象是指将对象抽象为具体类的过程;抽象只关注对象有哪些属性和行为(方法);
JDK: java开发工具包;包含JRE, javac等调优诊断工具;能够创建和编译程序;
JRE: java运行环境; 包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件;不能创建程序;
JVM:java虚拟机,提供运行字节码文件(.class)的环境支持;
jdk 包含jre ; jre 包含 jvm
开发设计类时需考虑的事情,面试中如果碰见能答几个就几个;
java主类是java代码运行的入口,即包含 main方法的类;
子类无法继承父类的构造器,所以构造器不能被重写(overidde),但可以被重载(overload);
重写
:
发生在父类与子类之间
方法名,参数列表,必须相同,返回值小于等于父类;
访问修饰符大于等于父类(public>protected>default>private);父类方法为private,则无法重写;
重抛出异常的范围要小于等于父类异常;
重载
:
==: 判定是否是相同一个对象 ,比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,;
equals: equals用来比较的是两个对象的内容是否相等; 但Object中的equals方法返回的却是==的判断 ;
hashCode() 的作用是获取哈希码,也称为散列码;它实际上一个int整数;哈希码的作用是确定该对象在哈希表中的索引位置;散列表存储的是键值对(key-value),即能根据键获取值;
当一个对象插入散列表时先会比较对象与散列表中已有的对象hash值,若不同,则直接插入散列表,若相同(hash碰撞),则会调用equals 方法检查是否真的相同, 如果equal()判断不相等,直接将该元素放入集合中,否则不放入;
值传递:传递了对象的一个副本,即使副本被改变,也不会影响源对象;
引用传递:着传递的并不是实际的对象,而是对象的引用;对外部对象的改变会反映到实际对象;
一般认为,Java 内的传递都是值传递,Java 中实例对象的传递是引用传递;
抽象类是对类的抽象,是一种模板设计; 而接口是行为的抽象,可以理解为行为的规范;
抽象类中可以包含非抽象方法;而接口是绝对的抽象方法;
接口默认是public 方法,java8中接口支持默认(default)方法;
一个类可以实现多个接口,但只能实现一个抽象类;
抽象类不能使用final修饰(final修饰的类为固定类,无法被继承)
tip: 数据量少的时候使用 String; 单线程使用StringBuilder ; 多线程使用 StringBuffer ; 使用StringBuilder 性能比 StringBuffer 性能 提升大概有 10%~15%;
2 << 3 = 8 ; 2 左移3位
& 运算符 按位与;
&& 运算符是短路与:&& 左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算
static 变量在 Java 中属于类的,它在所有的实例中具有相同的值。当类被 Java 虚拟机载入的时候,会对 static 变量进行初始化;故需要用实例来访问 static 变量;
类型 | 位数 | 字节数 |
---|---|---|
short | 2 | 16 |
int | 4 | 32 |
long | 8 | 64 |
float | 4 | 32 |
double | 8 | 64 |
char | 2 | 16 |
instanceof 严格来说是Java中的一个双目运算符,用来检查一个对象是否为一个类的实例;
浮点数为非精确值,应该使用BigDecimal来修饰金额;
tip: int 是基础数据类型,占用空间小; Integer 是对象占用空间大;
在idk 1.7之前,switch只能支持byte, short, char, int或者其对应的封装类以及Enum类型。从idk 1.7之后switch开始支持String。
可以用在byte上,但是不能用在long上。
可以使用 String 接收 byte[] 参数的构造器来进行转换, 但编码必须正确;
1.被final修饰的类不可以被继承
2.被final修饰的方法不可以被重写
3.被final修饰的变量不可以被改变。
5.被final修饰的常量,在编译阶段会存入常量池中。
Math.round(-1.5)的返回值是-1。四舍五入的原理是在参数上加0.5然后做向下取整
tring str="i"的方式,Java 虚拟机会将其分配到常量池中;而 String str=new String("i") 则会被分到堆内存中;所以一个是常量,一个是对象,不一样;
char 类型可以存储一个中文汉字,因为 Java 中使用的编码是 Unicode,一个 char 类型占 2 个字节,所以能放一个中文。
内部类:
1、内部类中的变量和方法不能声明为静态。
2、内部类实例化:B是A的内部类,实例化B: A.B b = new A().new B()
。
3、内部类可以引用外部类的静态或者非静态属性及方法。
静态内部类:
1、静态内部类属性和方法可以声明为静态的或者非静态的。
2、实例化静态内部类:B是A的静态内部类, A.B b = new A.B()
。
3、静态内部类只能引用外部类的静态的属性及方法。
断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式的值为false,那么系统会报告一个AssertionError。
断言有两种形式:
assert Expression1 assert Expression1 : Expression2
assert false; assert i == 0:"123";// 当 i不等于0 时会输出错误信息
序列化机制将序列化的Java对象转换为位字节序列,这些字节序列可以保存在磁盘上,或通过网络传输,以达到以后恢复成原来的对象,通常被序列化的要实现Serializable接口,并指定序列值
Externalizable 可以控制整个序列化过程,指定特定的二进制格式,增加安全机制
按照流的流向分,可以分为输入流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的角色划,可以分为节点流和处理流。
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
图片来源网络:
java.io
包,它是基于流模型实现的,交互的方式是同步、 阻塞方式IO ; 在读入输入流或者输出流时,在读写完成之前,线程会一直处于阻塞状态。
Collection:是java.uitl 下的接口,他是各种集合的父接口;
Conllecitons:是个java.util下的类,是针对集合的工具类,提供一系列静态方法对集合的搜索、查找、同步等操作;
List Set Map
共同点:
ArrayList
和 LinkedList
都是线程不安全;
区别:
Iterator迭代器可以对集合进行遍历, 遍历方式都是 hasNext()
和 next()
方法,,在当前遍历集合元素被更改的时候,就会抛出 ConcurrentModificationException
异常;
共同点: 都实现 Map接口;
区别:
TreeMap实现SortMap接口,能够将记录根据键排序(默认升序排序),也可以指定排序的比较器Comparator,当用Iterator 遍历TreeMap时得到排序后的结果;
对于插入、删除和定位元素等操作,选择HashMap;如果对一个有序的key集合进行遍历,选择TreeMap
并发集合常见的有 ConcurrentHashMap
、 ConcurrentLinkedQueue
、 ConcurrentLinkedDeque
等。并发集合位于 java.util.concurrent 包下,是 jdk1.5 之后才有;其相比与普通集合添加了 synchronized 同步锁,线程安全,但效率低;
jdk1.8的实现不再使用jdk1.7的Segment+ HashEntry分段锁机制实现,利用 Node数组
+ CAS+Synchronized
来保证线程安全;底层采用 数组+链表+红黑树
的存储结构;
ConcurrentHashMap1.7
dk1.7
ConcurrentHashMap1.8
目的是为了能让 HashMap 存取高效,尽量减少Hash碰撞,尽量使Hash算法的结果均匀分布,每个链表/红黑树长度大致相同;
算法实际是取模,hash%length,计算机中求余效率不如位移运算,源码中做了优化hash&(length-1);
hash%length==hash&(length-1)的前提是length是2的n次方
直接在初始化的时候就指定ArrayList的容量值;
根据集合的特点来选用集合;根据键获取值选用 Map
接口下的集合;需要排序选择 TreeMap
,不需要排序选择 HashMap
,需要线程安全选 ConcurrentHashMap
。
只存放元素值时,就选择实现 Collection
接口的集合;需要元素唯一时选择实现 Set
接口的集合,如TreeSet 或
HashSet; 不需要元素唯一性就选择实现 List 接口,如 ArrayList
或 LinkedList
;
快速失败:当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个集合时,就会抛出一个 ConcurrentModification 异常。 在 java.util 包下的都是快速失败。
安全失败:你在迭代的时候会去底层集合做一个拷贝,所以你在修改上层集合的时候是不会受影响的,不会抛出 ConcurrentModification 异常。在java.util.concurrent 包下的全是安全失败的。
附:
HashMap 源码分析: https://blog.csdn.net/youku1327/article/details/105332136;
ArrayList源码分析https://blog.csdn.net/youku1327/article/details/105314040
tip: 需要懂 HashMap,ArrayList,LinkedList,ConcurrentHashMap底层实现原理