所谓 API 就是一些已经写好、可直接调用的类库
注:右上方的悬浮框有目录索引
一、集合框架和泛型
1】Java集合框架是什么?框架的一些优点
- 每种编程语言中都有集合,最初的 Java 版本包含几种集合类:Vector、Stack、HashTable 和 Array。随着集合的广泛使用,Java 1.2 提出了囊括所有集合接口、实现算法的集合框架。在保证线程安全的情况下使用泛型和并发集合类,Java 已经经历了很久。它还包括在 Java 并发包中,阻塞接口以及它们的实现。
-
优点
-
- 降低开发成本
-
- 代码质量得到提高
-
- 降低代码维护成本
-
- 复用性和可操作性
@Override
// 自定义集合框架排序方法,根据实体类中唯一的值进行比较
public int compareTo(Student o) {
// TODO Auto-generated method stub
if(this.id == o.id){
return 0;
}else if(this.id > o.id){
return 1;
}else{
return -1;
}
}
2】集合框架中的泛型有什么优点?
- ( Java 1.5 引入了泛型 )
- 泛型允许我们为集合提供一个可容纳的对象类型
- 避免在运行出现 ClassCastException
- 使得代码更加整洁
- 不需要显示转换 和 instanceOf 操作符
/*
* instanceof 使用实例
*/
public static void main(String[] args) {
Father fatherOne = new Father();
Father fatherTwo = new Son();
// 判断 Father 类型的引用变量 fatherOne 是否指向了 Son 类的实例对象
if(fatherOne instanceof Son){
System.out.println("Father 类型的引用变量 fatherOne 指向 Son 的实例对象");
}else{
System.out.println("Father 类型的引用变量 fatherOne 并没有指向 Son 的实例对象");
}
System.out.println();
// 判断 Father 类型的引用变量 fatherOne 是否指向了 Son 类的实例对象
if(fatherTwo instanceof Son){
System.out.println("Father 类型的引用变量 fatherTwo 指向 Son 的实例对象");
}else{
System.out.println("Father 类型的引用变量 fatherTwo 并没有指向 Son 的实例对象");
}
}
3】Java 集合框架的基础接口有哪些?
4】为何 Map 接口不继承 Collection 接口?
- Map 不是集合,集合也是不 Map,因此 Map 继承 Collection 毫无意义
- 如果 Map 继承 Collection 接口,那么元素去哪儿?Map 包含 key-value 对,它提供抽取 key 或 value 列表集合的方法,但是它不适合“一组对象”规范
5】Iterator 是什么?
- Iterator 接口提供遍历任何 Collection 接口
- 可以从一个 Collection 中使用迭代器方法来获取迭代器实例
- 迭代器取代了 Java 集合框架中的 Enumeration
- 迭代器允许调用者在迭代过程中移除元素
二、实用类
1】如何将字符串转化成 int ?
- 使用包装类 Integer
System.out.println(Integer.valueOf("2")); // 将字符串转换成包装类的 Integer 对象
System.out.println(Integer.parseInt("123")); // 将字符串转换成 int 型变量
2】为什么在 Java 中存储密码要使用 char[] ,而不使用 String?
- String 是不可变的,当 String 创建之后,就不会再改变了
- char[] 是可变的,在用完之后可以将其改变,不会留下任何原始数据
3】如何将字符串转换成时间 Date?
public static void main(String[] args) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
date =sdf.parse("2000-10-10 10:10:10");
System.out.println("自定义时间为:"+date);
// 输出: 自定义时间为:Tue Oct 10 10:10:10 CST 2000
String customTime = sdf.format(date);
System.out.println("\n自定义时间加格式后为:"+customTime);
// 输出: 自定义时间加格式后为:2000-10-10 10:10:10
} catch (ParseException e) {
e.printStackTrace();
}
}
4】字符串对象 String,StringBuilder,StringBuffer 之间的区别?
- 只有 String 是不可变的(即:不可自由增加或者删除字符串)
- StringBuilder:是线程不安全的
- StringBuffer:是线程安全的
注:大量字符拼接时,建议使用 StringBuilder、StringBuffer
5】计算一个字符串某个字符的出现次数?
- (一)使用 chartAt 方法截取后,循环判断
- (二)使用 apache.commons.lang 包中的 StringUtils
public static void main(String[] args) {
String customChar = new Scanner(System.in).next();
int count=0;
String str = "abcdefghijklmnopqrstuvwxyz,abcdefghijklmnopqrstuvwxyz,abcdefghijklmnopqrstuvwxyz";
for(int i=0;i<str.length();i++){
if(str.charAt(i)==customChar.charAt(0)){
count++;
}
}
// 计算字符串某个字符出现的数次
System.out.println(customChar.charAt(0)+"在字符中出现:"+count);
// 计算字符串中某个字符串出现的数次
System.out.println("StringUtils 方法计算得出:"+StringUtils.countMatches(str, customChar));
}
三、输入和输出处理
1】java 中有几种类型的流?JDK 为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?
-
字节流、字符流( 输入流、输出流 )
-
- 字节流继承于 InputStream、OutputStream
-
- 字符流继承于 Reader、Writer。在 java.io 包中还有许多其他的流,
-
- 流主要是为了提高性能和使用方便。
2】什么是 java 序列化,如何实现 java 序列化?
-
处理对象流的机制,将对象内容流化
-
- 需要被序列化的类实现 Serializale 接口
-
- 使用输出流构造 ObjectOutputStream(对象流)
-
- 使用 writeObject(Object obj)
@SuppressWarnings("serial")
public class User implements Serializable{
// 成员变量
private String user_name;
private String user_password;
// 无法序列化的成员变量
transient private String user_Jurisdiction;
// --- 构造方法 ---
// 此处省略(Alt+Shift+S 组合键选择 Constructors from superclass... 和 Constructors from using Fields...,自动生成代码即可)
// --- get / set 方法 ---
// 此处省略(Alt+Shift+S 组合 键选择 Generate Getters and Setters...,自动生成代码即可)
// --- toString ---
// 此处省略(Alt+Shift+S 组合 键选择 Generate toString()...,自动生成代码即可)
// 入口函数,测试方法,建议在测试类中编写
public static void main(String[] args) {
// 先创建文件,将序列化后的对象保存到文件中
File file = new File("text.txt");
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("文件创建异常!");
e.printStackTrace();
}
}
// 使用流对对象进行操作
User user = new User("Ajax","ajax","0");
try {
// 创建输出流,将对象写入文件
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(user);
oos.flush();
// 创建输入流,将对象信息从文件中输出到控制台
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
User new_user = (User)ois.readObject();
// 输入读取到的反序列化信息
System.out.println(new_user.toString());
// 关闭流
ois.close();
fis.close();
oos.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
3】使用处理流的优势有哪些?如何识别所使用的流是处理流还是节点流
-
-优势-
-
- 使用处理流操作更简单,效率更高
-判别-
-
- 处理流(包装流)的构造器参数不是一个物理节点,而是已经存在的流
-
- 节点流都是直接以物理 IO 及节点作为构造器参数的,直接与数据源相联
4】什么是标准的 I/O 流?
- 在 Java 中:stdin 表示键盘、stdout 表示监视器
- System.in 和 System.out 及 System.err 统称为标准流
public final static InputStream in = nullInputStream();
public final static PrintStream out = nullPrintStream();
public final static PrintStream err = nullPrintStream();
5】什么能被序列化?什么不能被序列化?
-
可以序列化
-
- 属性
-
- 类名
不可以序列化
-
- static 的属性
-
- 方法
-
- 加了 transient 修饰符的属性
四、XML
1】XML 是什么?
- XML 是可扩展标记语言( Extensible Markup language )
- 可以根据自己的需要扩展 XML
- XML 中可以轻松定义:自定义标签
2】DTD 与 XML Schema 有何区别?
-
DTD
-
- 不使用 XML 编写 XML 文件
-
- 是文档类型描述(Document Type definition)是定义 XML 文件结构的传统方式
XML Schema
-
- 本身就是 XML 文件
-
- XML 解析器等已有 XML 工具可以用来处理 XML Schema
-
- 设计于 DTD 之后,提供了更多的类型来映射 XML 文件不同的数据类型
3】XML CDATA 是什么?
- CDATA 是指字符数据,它有特殊的指令被 XML 解析器解析
- XML 解析器解析 XML 文档中所有的文本,标签的值也会被解析,因为标签值也可能包含 XML 标签。
- CDATA 部分不会被 XML 解析器解析
- CDATA 部分以结束
4】XSLT 是什么?
- XSLT 也是常用的 XML 技术,用于将一个 XML 文件转换为另一种 XML、HTML或者其他格式
- XSLT 为转换 XML 文件详细定义了自己的语法,函数和操作符。
- 通常由 XSLT 引擎完成转换,XSLT 引擎读取 XSLT 语法编写的 XML 样式表或者 XSL 文件的指令。
- XSLT 大量使用递归来执行转换。
- 一个常见 XSLT 使用就是将 XML 文件中的数据作为 HTML 页面显示。
- XSLT 也可以很方便地把一种 XML 文件转换为另一种文档
5】DOM 和 SAX 解析器有什么区别?
- DOM 和 SAX 解析器的主要区别在于它们解析 XML 文档的方式。
- 使用 DOM 解析时,XML 文档以树形结构的形式加载到内存中
- SAX 是事件驱动的解析器
五、Java 反射机制
1】反射获取字节码对象方式、创建对象的两种方式?
-
获取字节码方式三种
-
- 类名.class 例:System.class
-
- 对象.getClass() 例:new Date().getClass();
-
- Class.forName(“类名”) 例:Class.forName(“java.util.Date”);
创建对象的两种方式
-
- 直接使用字节码创建对象,只能调用默认的构造方法:字节码.newInstance();
-
- 获取构造方法 Constructor,然后调用构造方法创建,可以通过参数不同调用不同的构造方式
2】怎么理解反射,反射的应用?
- 在运行状态下,通过类的字节码文件去解剖一个类,使用类的构造方法、成员变量、成员函数
- 反射就是把 Java 类中的各种成分映射成相应的 Java 类。
- 一般情况下我们要解决某个问题,先找到相关的类,创建该类的对象,然后通过该对象调用对应的方法来解决问题。反射是一个正好相反的过程,开始可能并没有解决这个问题,而我们却先用一个当时可能并不存在的方法解决了这个问题,后来才有的这个类。这其实就是框架的原理,先有的框架再有的解决问题的类。
- 框架描述了整体,制订了功能方法的规范,具体的实现之后按照这个规范编写。这些都需要靠反射来完成。使用框架有良好的扩展性,某部分功能的优化不需要涉及程序整体,只需要修改特定的部分就好了,然后通过配置文件,获取对应的类名,就可以了。
3】什么是 reflection(反射)?
- Java 中的反射是一种强大的工具,它能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行链接。
- 反射允许在编写与执行时,使程序代码能够接入装载到 JVM 中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活应用的主要工具。
- 需要注意的是,如果使用不当,反射的成本会很高
4】反射的原理是什么?
- 反射是为了能够动态的加载一个类,动态的调用一个方法,动态的访问一个属性等动态要求而设计的。
- 它的出发点就在于 JVM 会为每个类创建一个 java.lang.Class 类的实例,通过该对象可以获取这个类的信息,然后通过使用 java.lang.reflect 包下的 API 以达到各种动态需求。
5】Class 类的含义和作用是什么?
- 第一个 Class 类的对象就代表了一种被加载进入 JVM 的类,它代表了该类的一种信息映射。开发者可以通过三种途径获取到 Class 对象。
- Class 的 forName() 方法的返回值就是 Class 类型,也就是动态导入类的 Class 对象的引用。
public static Class<?> forName(String className) throws ClassNotFoundException
- 每个类都会有一个名称为 Class 的静态属性,通过它也是可以获取到 Class 对象的,示例代码如下:
Class<Student> class = Student.class; // 访问 Student 类的 class 属性
- Object 类中有一个名为 getClass 的成员方法,它返回的是对象的运行时类的 Class 对象。因为 Object 类是所有类的父类,所以所有的对象都可以使用该方法得到它运行时类的 Class 对象,示例代码如下:
Student stu = new Student(); Class<Student> class = stu.getClass();// 调用 Student 对象 getName 方法
六、实例(1)
1】什么是 Java 集合 API?
- Java 集合 API 是用来表示和操作集合的统一框架,包括接口、实现类以及帮助程序员完成一些编程的算法。
2】线程和进程有什么区别?
- 线程是进程的子集
- 不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。
3】如何在 Java 中实现线程?
- 在语言层面有两种方式
- java.lang.Thread 类的实例就是一个线程,但是它需要调用 java.lang.Runnable 接口来执行
- 由于线程本身就是调用的 Runnable 接口所以 可以继承 java.lang.Thread 类 或者 直接调用 Runable 接口来重写 run() 方法 实现线程
4】Iterator 和 ListIterator 的区别是什么?
- Iterator 可以遍历 Set 和 List 集合,而 ListIterator 只能遍历 List
- Iterator 只可以向前遍历,而 ListIterator 可以双向遍历
- ListIteraotr 从 Iteraotr 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置
5】HashMap 和 HashTable
- 两者老师用 key-value 方式获取数据。Hashtable 是原始集合类之一(也称遗留类)
- HashMap 作为新集合框架的一部分在 Java2 的 1.2 版本中加入。
-
区别
-
- HashMap 允许 key 和 value 为 null,而 HashTalbe 不允许
-
- HashTable 是同步的,而 HashMap 不是。所以 HashMap 适合单线程,HashTable 适合多线程
-
- HashMap 提供对 key 的 Set 进行遍历,因此这是 fail - fast 的,但 HashTalbe 提供对 key 的 Enumeration(枚举类) 进行遍历,它不支持 fail - fast。
-
- HashTable 被认为是个遗留的类,如果寻求在迭代的时候修改 Map,应使用 CocurrentHashMap
fail-fast
fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。
Hashtable<String, String> ht = new Hashtable<String, String>();
for (int i = 0; i < 100; i++) {
ht.put("Key=" + i, "Val=" + i);
}
Enumeration<String> en = ht.keys();
while (en.hasMoreElements()) {
System.out.println(en.nextElement());
}
七、实例(2)
1】如何决定选用 HashMap 不是 TreeMap?
- 对于在 Map 中插入、删除和定位元素这类操作,HashMap 是最好的选择。
- 若要对一个有序的 key 集合进行遍历,TreeMap 会更好
- 基于 collection 的大小,也许向 HashMap 中添加元素会更快,将 map 换为 TreeMap 进行有序 key 的遍历
2】在 HashTable 中上下文同步是什么意思
- 同步意味着在一个时间点只能有一个线程只可惜修改哈希表
- 任何线程在执行 hashtable 的更新操作前需要获取对象锁,其他线程等待锁的释放
3】哪些集合类提供对元素的随机访问
- ArrayList、HashMap、TreeMap 和 HashTable
4】有三个线程 T1、T2、T3,怎么确保它们按顺序执行
- join() 方法
- 在一个线程中启动另一线程,另一线程完成执行后,再执行本线程
5】Java 多线程中调用 wait() 和 sleep() 方法有什么不同?
- Java 程序中 wait 和 sleep 都会造成某种形式的暂停,它们可以满足不同的需要。
- wait() 方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而 sleep() 方法仅仅释放 CPU 资源或者让当前线程停止执行一段时间,但不会释放锁。