白_Java_高级_API


所谓 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 对象。
  1. Class 的 forName() 方法的返回值就是 Class 类型,也就是动态导入类的 Class 对象的引用。
    public static Class<?> forName(String className) throws ClassNotFoundException
  2. 每个类都会有一个名称为 Class 的静态属性,通过它也是可以获取到 Class 对象的,示例代码如下:
    Class<Student> class = Student.class; // 访问 Student 类的 class 属性
  3. 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 资源或者让当前线程停止执行一段时间,但不会释放锁。

猜你喜欢

转载自blog.csdn.net/ice_debj/article/details/103674273
今日推荐