一.JDK JRE JVM的关系?
1.JDK是java的核心,包括了Java运行环境JRE、JVM和Java工具和Java基础类库
2.JRE是运行JAVA的运行时环境,包含JVM和Java核心类库。
3.JVM是java虚拟机的缩写,是整个java实现跨平台的最核心的部分,能够运行以Java语言写作的软件程序。
二.JAVA的基本类型有哪些,和引用类型的区别?
1.基本类型的值就是一个数字,一个字符或者一个布尔值.
八大基本类型byte,short,int,long,foiat,double,char,boolean
2.引用类型:
是一个对象类型,他的值是指向内存空间的引用
引用数据 类型如:( 类Class,接口Interface,数组[] )
三.访问修饰符 public,private,protected,以及不写(默认)时的区别
1 public : 对所有类可见。使用对象:类、接口、变量、方法
2 private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
3 protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
4 default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
四.final finally finalize区别?
- final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表
- finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。 - finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
五.this和super的区别?
- this是代表本类对象的引用,super代表父类的对象引用
- this用于区分局部变量和成员变量,super用于区分本类变量和父类变量
- this和super不能同时出现在同一个构造方法中
- this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
六.break ,continue ,return 的区别及作用
- break 跳出总上一层循环,不再执行循环(结束当前的循环体)
- continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)
- return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)
七.JAVA常见的内部排序算法有哪些?写出冒泡排序
- 排序算法可以分为内部排序和外部排序。
内部排序是数据记录在内存中进行排序。
外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。
常见的内部排序算法有:冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序等。
- 冒泡排序,是通过每一次遍历获取最大/最小值
将最大值/最小值放在尾部/头部
然后除开最大值/最小值,剩下的数据在进行遍历获取最大/最小值
3.代码如下:
public static void main(String[] args) {
int arr[] = {8, 5, 3, 2, 4};
//冒泡
for (int i = 0; i < arr.length; i++) {
//外层循环,遍历次数
for (int j = 0; j < arr.length - i - 1; j++) {
//内层循环,升序(如果前一个值比后一个值大,则交换)
//内层循环一次,获取一个最大值
if (arr[j] > arr[j + 1]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
3.1 排序过程(红色:移动的数据)
5,3,2,4,8
3,2,4,5,8
2,3,4,5,8
2,3,4,5,8
2,3,4,5,8
- 其它排序算法参考:https://www.cnblogs.com/ll409546297/p/10956960.html
八.抽象类(abstract class) 和接口( interface) 有什么区别?
-
相同点:
A. 两者都是抽象类,都不能被实例化他们的子类都实现已声明的方法
B.可以将抽象类和接口类型作为引用类型
C. 一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类 -
不同点:
A. interface实现需要通过implements , 而abstract 需要继承用extends.
B. 一个类可以实现多个interface,但一个类只能继承一个abstract class.
C. interface强调特定功能的实现,而abstract class强调所属关系
D. 尽管interface实现类及abstrct class的子类都必须要实现相应的抽象方法,但实现的形式不同。interface中的每一个方法都是抽象方法,都只是声明的 (declaration, 没有方法体),实现类必须要实现。而abstract class的子类可以有选择地实现
九.java和其他编程语言有什么优势?
- java是目前应用最为广泛的网络编程语言,是一门强类型语言,它具有简单,安全,健壮,面向对象,跨平台性;
- 跨平台性依赖于jvm虚拟机,(.java文件)通过编译器编译成为Class文件(字节码文件),而它的class文件是基于字节码(以byte为单位存储的文件)的,而字节码文件是描述程序要运行的的虚指令的集合;
十.面向对象的基本特征,各特征有什么优点?
面向对象的三大特征,封装,继承,多态.
-
封装性:private关键字修饰
类的封装性为类的成员提供公有、缺省、保护和私有等访问权限,目的是隐藏类中的私有变量和类中方法的实现细节 -
继承:extends关键字修饰
A.java只支持单继承,可以传递(爷爷,儿子,孙子的关系)
B.相当于子类把父类的功能复制了一份,不能继承父类的私有成员
C.像是is a 的关系,多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展
3.多态:
指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
多态特点:
A.编译看左边,运行看右边
B. 要有方法的重写
C. 父类引用指向子类对象,如:Animal a = new Dog(); – 小到大,向上转型
D.多态的前提是继承
E.多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法。
F.提高了程序的扩展性和可维护性
注意:默认情况下面向对象有 3 大特性,封装、继承、多态,如果面试官问让说出4 大特性,那么我们就把抽象加上去。
十一.什么是String?他和StringBuilder/StringBuffer有什么区别?
一. String
- 是一个封装char[]数组的对象.
- String是引用类型,底层是被final修饰的字符数组.是不可变的字符,每拼接一次就会产生一个新的对象,而由于垃圾回收机制的原理,原有的对象不会立马被回收,这是对内存极大的消耗
- 利用 String 类,在做字符串拼接的过程效率极其低下
- 创建String对象:
二.StringBuilder/StringBuffer - StringBuilder(线程不安全)和StringBuffer(线程安全)底层是可变的字符数组
- StringBuilder和StringBuffer 是可变长度的,可以利用append方法向原有对象拼接,然后用toString方法将其转化为String类型;这两个相比起来StringBuilder的效率更高,因为他是非线程安全的,不需要花费资源去维护同步锁。
- 使用场景
(1).如果要操作少量的数据使用String。
(2).单线程操作字符串缓冲区下操作大量数据使用StringBuilder。
(3).多线程操作字符串缓冲区下操作大量数据使用StringBuffer。
(4)StringBuilder一般使用在方法内部来完成类似"+"功能,因为是线程不安全的,所以用完以后可以丢弃。StringBuffer主要用在全局变量中
(5) 在执行效率上,StringBuilder > StringBuffer > String
(6)源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。
十二.序列化/反序列化
-
序列化:是指把java程序中的对象,永久存储到磁盘的过程。–out
–ObjectOutputStream -
反序列化:是指把磁盘中的已经 序列化好的文件 恢复到 java程序中来。-- in
–ObjectInputStream
特点/应用场景
1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。
2、 不需要序列化的数据可以被修饰为static的,由于static属于类,不随对象被序列化输出。
3、 不需要序列化的数据也可以被修饰为transient临时的,只在程序运行期间,在内存中存在不会被序列化持久保存。
4、 在反序列化时,如果和序列化的版本号不一致时,无法完成反序列化。
5、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。
6、 常用于服务器之间的数据传输,序列化成文件,反序列化读取数据。
7、 常用于使用套接字流在主机之间传递对象。
十三.泛型的作用
- 通过泛型的语法定义,约束集合元素的类型,进行安全检查,把错误显示在编译期
泛型:在类上定义的泛型用于约束类中属性,方法参数,方法返回值类型. - 代码通用性更强,后面有案例
- 泛型可以提升程序代码的可读性,但它只是一个语法糖(编译后这样的东西就被删除,不出现在最终的源代码中),对于JVM运行时的性能是没有任何影响的。
- // 测试 泛型的通用性
public class Test1_Generic {
public static void main(String[] args) {
Integer[] a = { 1, 2, 3, 4, 5 };
Double[] b = {1.1,2.2,3.3,4.4,5.5};
String[] c = {"a1","a2","a3","a4"};
print(a);
print(b);
print(c);
}
//1、泛型可以使用在类(接口)上,也可以使用在方法上(返回值前+参数列表)
//2、约束了参数类型是泛型类型
private static <E> void print(E[] a) {
//普通for foreach :效率上foreach>普通for。语法上foreach简洁。
//用处:普通for可以按照下标获取元素,foreach不可以。
// for (int i = 0; i < a.length; i++) { syso(a[i]); }//低效
// 高效for循环 foreach循环 语法: for(数据的类型 变量名 : 要遍历的数据)
for (E in : a) {
System.out.println(in);//打印获取到的数据
}
}
}
二. 常用名称
1 E - Element (在集合中使用,因为集合中存放的是元素)
2 T - Type(Java 类)
3 K - Key(键)
4 V - Value(值)
5 N - Number(数值类型)
6 ? - 表示不确定的java类型
十四.集合
一 集合和数组有什么区别?
数组:大小固定,只能存储相同数据类型的数据
集合:大小可动态扩展,可以存储各种类型的数据
转换
数组转换为集合:Arrays.asList(数组)
int[] arr = {1,3,4,6,6};
Arrays.asList(arr);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
集合转换为数组:集合.toArray();
List list = new ArrayList();
list.add("a");
list.add("b");
list.toArray();
System.out.println(list.toString());
二.集合的结构
Collection是根接口。既然是接口就不能创建对象,我们只能学习他的共性方法。
List接口
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不同,列表通常允许重复的元素
–特点:元素都有索引,元素可以重复,元素有序。
ArrayList和LinkedList
一.ArrayList
–1、ArrayList特点
–底层维护了一个数组,默认初始容量是10。
–初始容量不够会自动按照1.5倍的方式扩容。
–ArrayList底层维护很多操作的方法,本质上就是对数组的操作。
–适合用于查询多增删少的场景。
–2、创建对象
ArrayList() 构造一个初始容量为 10 的空列表。
–3.ArrayList扩容
ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,将ArrayList的容量变为10 (如下图一);之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15(如下图二);当添加第16个数据时,继续扩容变为15 * 1.5 =22个
二.LinkedList
–1、特点
–底层维护了一个链表结构。
–适用于增删多而查询少的场景。
–对于链表中的节点操作效率并不高,但是对于首尾两个节点操作效率高。
–2、创建对象
LinkedList()
构造一个空列表。
Set接口
1.–特点:元素无序(set集合没有下标)
不可重复 – 由于集合中的元素不可以重复。常用于给数据去重。
没有索引。
2.Ø HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
HashSet实现类
–特点
此类实现 Set 接口,由哈希表/散列表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
–创建对象
HashSet()
构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75
Ø TreeSet:底层就是TreeMap,也是红黑树的形式,便于查找数据。
Ø HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据。
3.Set集合给自定义–测试对象去重!!
–如果想利用set集合给自定义对象去重,需要同时重写hashCode()和equals()
//这个类用来测试 Set集合自定义对象去重!
//总结:
//!!如果想要使用set集合,给你的自定义 对象 去重的话 ,,需要同时重写hashCode() 和equals()
//重写hashCode():原来的实现方式是:只要new就会给计算一个新的哈希码值。
//现在需要按照对象的属性值计算哈希码值,就算new两次,属性值一样时也必须产生相同哈希码值
//重写equals():原来比的是两个对象间的地址值,现在要去比较两个对象间的属性值,如果属性值都一样,必须相同
public class Test1_Set {
public static void main(String[] args) {
HashSet<Student> set = new HashSet<>();
// 创建元素
Student s1 = new Student("西门庆", 20);
Student s2 = new Student("武大郎", 19);
Student s3 = new Student("潘金莲", 21);
Student s4 = new Student("小龙女", 23);
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
Student s5 = new Student("潘金莲", 21);
Student s6 = new Student("小龙女", 23);
//!!!往set中添加重复元素--属性值完全相同的两个对象没给去重!!
set.add(s5);
set.add(s6);
System.out.println(s3.hashCode());
System.out.println(s5.hashCode());
//满足以下的判断条件,才能给自定义对象去重!!
// if ( p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
//条件1:p.hash == hash --判断两个对象的hash值一样吗?不一样!
//需求1:就算new两次,只要两个对象间的属性值完全一样,给我产生一样的哈希码值就好了 - 重写hashCode()
//条件2:key.equals(k)--让两个对象间的equals()返回true - 重写equals()
System.out.println(set);
}
}
class Student {
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Map接口<K,V>
–1、概述
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
一些映射实现则不保证顺序,如 HashMap 类
–2.类型参数: K - 此映射所维护的键的类型V - 映射值的类型。
也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复.
–3.特点
Ø 可以根据键 提取对应的值
Ø 键不允许重复,如果重复值会被覆盖
Ø 存放的都是无序数据
Ø 初始容量是16,默认的加载因子是0.75
.HashMap
–1.概述
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
–2、原理
–当需要向map中存储元素时,底层会根据hash算法计算对象的存储位置。
–如果这个位置上没有存过元素,就直接存放,就相当于直接作为数组的元素存在。
–如果这个位置上存过数据,就会形成链表的结构–hash碰撞/冲突
–我们尽量要让每个对象拥有自己的哈希值,尽量放在数组结构上。避免链表的形成,因为链表查询效率低。