- 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
- 含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)
- 占内存大小 字符常量只占两个字节 字符串常量占若干个字节(至少一个字符结束标志)
不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。
(了解)基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。
3.String有哪些特性不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。
final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。
4.String s = new String(“xyz”);创建了几个字符串对象两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象
5.数组有没有 length()方法?String 有没有 length()方法数组没有 length()方法 ,有 length 的属性。String 有 length()方法。Javascript中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。
6.BIO和NIO的问题以及优化方式https://blog.csdn.net/weixin_47681942?type=blog
7.下面程序的输出结果是多少?public class Test extends Date{
public static void main(String[] args) {
new Test().test();
}
public void test(){
System.out.println(super.getClass().getName());
}
}
结果:Test
在 test 方法中,直接调用 getClass().getName()方法,返回的是 Test 类名
由于 getClass()在 Object 类中定义成了 final,子类不能覆盖该方法,所以,在 test 方法中调用 getClass().getName()方法,其实就是在调用从父类继承的 getClass()方法,等效于调用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也应该是 Test。
如果想得到父类的名称,应该用如下代码: getClass().getSuperClass().getName();
异常是指 java 程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java 使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。
(要说)所有异常的根类为java.lang.Throwable,Throwable 下面又派生了两个子类:Error 和 Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception 表示程序能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
(解决方案)java 为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须 try…catch 处理或用 throws 声明继续抛给上层调用方法处理,所以普通异常也称为 checked 异常,而系统异常可以处理也可以不处理,所以,编译器不强制用 try…catch 处理或用 throws 声明,所以系统异常也称为 unchecked 异常。
9.请简述泛型擦除- 真泛型:泛型中的类型是真实存在的。
- 伪泛型:仅于编译时类型检查,在运行时擦除类型信息。
Java的泛型是伪泛型。为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
10.介绍 Collection 框架的结构随意发挥题,天南海北谁便谈,只要让别人觉得你知识渊博,理解透彻即可。
11.HashSet如何检查重复(HashSet是如何保证数据不可重复的)?hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
检查流程:当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。
hashCode()与equals()的相关规定(判断选择)
如果两个对象相等,则hashcode一定也是相同的
两个对象相等,对两个对象分别调用equals方法都返回true
两个对象有相同的hashcode值,它们也不一定是相等的
1、linkedList Vector ArrayList的区别(1)从存储数据结构分析 ArrayList:数组 Vector:数组 linkedList:双向链表
数组:可以根据下标快 速查找,所以大部分情况下,查询快。但是如果要进行增删操作的时候,会需要移动 修改元素后面的所 有元素,所以增删的开销比较大,数组的对增删操作的执行效率低。而采用数组作为数据存储 结构的 ArrayList、Vector也存在这些特性,查询速度快(可以根据下标直接取,比迭代查找更快),增删慢。
链 表:增加和删除元素方便,增加或删除一个元素,仅需处理结点间的引用即可。就像人手拉手连成一 排, 要增加或删除某个人只要附近的两个人换一个人牵手,对已经牵好手的人没影响。无论在哪里换人 耗费的资源和 时间都是一样的。但是查询不方便,需要一个个对比,无法根据下标直接查找。而采用链 表结构存储的 linkedList也有这些特性,增删方便,查询慢(指的是随机查询,不是顺序查询)。
(2)从并发安全上分析 线程 class{ private int age; main(){ } }Vector:线程安全 synchronized 效率低了 Colllections ArrayList:非线程安全 效率高 linkedList:非线程安全
(3)数据增长分析 Vector:缺省的情况下,增长为原数组长度的一倍。说到缺省,说明他其实是可以 自主设置初始化大小的。 ArrayList:自动增长原数组的50%。老容量+老容量>>1
2、List接口和Set接口的特点共同特点:都继承Collection。
List:元素是有序的,元素可以重复。因为该集合体系有索引。 ArrayList:底层的数据结构使用的是顺序结构。特点:查询速度很快。但是增删稍慢。线程不同步。 linkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。 Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。 Stack:它用于模拟了“栈”这种数据结构,“栈”通常是指“后进先出”的容器。
Set:元素是无序,元素不可以重复。 HashSet:实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set的迭 代顺序; 特别是它不保证 该顺序恒久不变,此类允许使用 null元素。 TreeSet:使用元素的自然顺序对元素进行排序 linkedHashSet:使用链表维护了一个添加进集合中的顺序。导致当我们遍历 linkedHashSet集合元 素时,是按照添加进去的顺序遍历的!
3、假设顺序列表ArrayList中存储的元素是整型数字1~5,遍历每个元素,将每个元素顺 序输出。(你能想到的所有方式)package com.briup.work;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
public class Demo {
public static void main(String[] args) {
List list = new ArrayList(Arrays.asList(1,2,3,4,5));
System.out.println("直接打印输出"+list);
System.out.println("for循环遍历");
for(int i = 0;i{
System.out.print(a+" ");
});
}
}
4、创建两个Set集合,判断这两个集合是否有交集,并打印出他们的交集
package com.briup.work;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class Demo3 {
public static void main(String[] args) {
Set set1 = new HashSet(Arrays.asList(1,2,4,5,6));
Set set2 = new HashSet(Arrays.asList(1,4,5));
//第一种保留集合里面共有的
//第二种移出参数集合独有的
set1.removeAll(set2);
System.out.println(set1);
}
}
5、ArrayList去除集合中字符串的重复值(字符串的内容相同)
ArrayList oldList = new ArrayList();
oldList.add("aa");
oldList.add("aa");
oldList.add("ab");
oldList.add("ab");
oldList.add("ac");
oldList.add("ac");
ArrayList newList = new ArrayList();
oldList.forEach((a) -> {
if (!newList.contains(a)) {
newList.add(a);
}
});
newList.forEach((b) -> {
System.out.println(b);
});
6.说说 List,Set,Map 三者的区别?
- List(对付顺序的好帮手): 存储的元素是有序的、可重复的。
- Set(注重独一无二的性质): 存储的元素是无序的、不可重复的。
- Map(用 Key 来搜索的专家): 使用键值对(key-value)存储,类似于数学上的函数 y=f(x),“x”代表 key,"y"代表 value,Key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
不可以。Map没有继承Iterable接口,而迭代器方法是Iterable接口的抽象方法
2.map的键和值能为空吗?为什么?HashMap的键和值可以为空,HashTable的键和值都不能为空
3.一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?主要作用是完成对类对象的初始化工作。
可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。
4.编写关于一个星期week的枚举代码,枚举值为英文名称的星期一到星期天,打印中 文的格式的星期名称。第一种方式
package com.briup.collection;
enum Week {
yi, er, san, si, wu, liu, qi;
}
public class Demo {
public static void main(String[] args) {
String day2 = Week.er.name();
;
String day = Enum.valueOf(Week.class, "er").name();
switch (day) {
case "yi":
System.out.println("星期一");
break;
case "er":
System.out.println("星期二");
break;
case "san":
System.out.println("星期三");
break;
case "si":
System.out.println("星期四");
break;
case "wu":
System.out.println("星期五");
break;
case "liu":
System.out.println("星期六");
}
}
}
第二种方式
public class WeekTest {
@Test
public void print() {
System.out.println(Week1.FRIDAY);
}
}
enum Week1 {
MonDAY("星期一"), TUESDAY("星期二"), WEDEDAY("星期三"), THURSDAY("星期四"), FRIDAY(
"星期五"), SATURADAY("星期六"), SUNDAY("星期天");
private Week1(String name) {
}
}
5.输出以下枚举类型对象的个数
enum Season{
SPRING,SUMMER,AUTUMN,WINTER;
}
答案:
public static void main(String[] args) {
//获取枚举类型的所有枚举元素
//枚举元素的数据类型就是当前的枚举类型 并且是静态常量
Season[] values = Season.values();
//打印数组长度
System.out.println(values.length);
}
6.HashMap 和 Hashtable 的区别
- 线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的,因为 HashTable 内部的方法基本都经过synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!);
- 效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;
- 对 Null key 和 Null value 的支持: HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个;HashTable 不允许有 null 键和 null 值,否则会抛出 NullPointerException。
- 初始容量大小和每次扩充容量大小的不同 : ① 创建时如果不指定容量初始值,Hashtable 默认的初始大小为 11,之后每次扩充,容量变为原来的 2n+1。HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍。② 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为 2 的幂次方大小(HashMap 中的tableSizeFor()方法保证,下面给出了源代码)。也就是说 HashMap 总是使用 2 的幂作为哈希表的大小,后面会介绍到为什么是 2 的幂次方。
- 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。



