程序员大部分时间都是在解决Bug,当我解决Bug时,总有一种隐隐的感觉,感觉我在寻找迷宫的入口。
我围着迷宫一直转圈,每转一圈,对他越熟悉,越了解,就越接近入口。好比最近的非常火的美剧《西部世界》,机器人死千百次,每次都是重复,每次重复都不一样,重复到最后,竟然有了自己的意识。
我尝试着各种方法,探究Bug迷宫的究竟,为什么会这样,模拟器是最好的老师,他公正的反馈你的每一处细微的修改,调整,当我一点点将这些反馈信息收集到我的大脑中进行处理时,一点点明白了为什么,终于将找到迷宫入口!
那欣喜,那快感,只有经过一行行代码排查才会有,我们做的就是电视剧里的侦探的工作
这叫先痛而后快
面试也是这样,经过一次次尝试,一次次靠近应聘迷宫入口,你就是面霸
要有耐心,相信自己
这篇博客还是解析Java SE 面试问题,上篇博客面试心得与总结<一>解析了三十个常见Java面试题,太长了,所以分两篇继续解析Java
一、Java IO与NIO
什么时NIO:
nio是new io的简称,从jdk1.4就被引入了,可以说不是什么新东西了。nio的主要作用就是用来解决速度差异的。举个例子:计算机处理的速度,和用户按键盘的速度。这两者的速度相差悬殊。如果按照经典的方法:一个用户设定一个线程,专门等待用户的输入,无形中就造成了严重的资源浪费:每一个线程都需要珍贵的cpu时间片,由于速度差异造成了在这个交互线程中的cpu都用来等待。 在以前的 Java IO 中,都是阻塞式 IO,NIO 引入了非阻塞式 IO。
面向流与面向缓冲:
Java IO是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。
Java IO是阻塞IO,而NIO是非阻塞IO:
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
选择器(Selectors):
Java NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上,然后使用一个线程来监视这些通道:若这些通道里有某个准备好可以开始进行读或写操作了,则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。
二、 反射的作用于原理
反射的作用概括地说是运行时获取类的各种定义信息,比如定义了哪些属性与方法。原理是通过类的class对象来获取它的各种信息
package com.softpo;
public class People {
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void speak() {
System.out.println(getName() + " " + getAge());
}
}
获取Class方式:
1)若在编译期知道一个类的名字,我们可以这样获取它的Class对象
Class peopleClass = People.class;
2)还有一种根据类的完整路径名获取Class对象的方法如下所示
Class peopleClass = Class.forName(“com.softpo.People”);
通过反射获取构造方法
public static void main(String[] args) {
Class pClass = People.class;
System.out.println(pClass);
try {
Constructor constructor = pClass.getConstructor(String.class, int.class);
People people = constructor.newInstance("Bill", 18);
obj.speak();
} catch (Exception e) {
e.printStackTrace();
}
}
学习更多,点点点
三、泛型常用特点,List能否转为List
1、Why ——引入泛型机制的原因
假如我们想要实现一个String数组,并且要求它可以动态改变大小,这时我们都会想到用ArrayList来聚合String对象。然而,过了一阵,我们想要实现一个大小可以改变的Date对象数组,这时我们当然希望能够重用之前写过的那个针对String对象的ArrayList实现。
在Java 5之前,ArrayList的实现大致如下:
public class ArrayList {
public Object get(int i) { ... }
public void add(Object o) { ... }
...
private Object[] elementData;
}
从以上代码我们可以看到,用于向ArrayList中添加元素的add函数接收一个Object型的参数,从ArrayList获取指定元素的get方法也返回一个Object类型的对象,Object对象数组elementData存放这ArrayList中的对象, 也就是说,无论你向ArrayList中放入什么类型的类型,到了它的内部,都是一个Object对象。
基于继承的泛型实现会带来两个问题:第一个问题是有关get方法的,我们每次调用get方法都会返回一个Object对象,每一次都要强制类型转换为我们需要的类型,这样会显得很麻烦;第二个问题是有关add方法的,假如我们往聚合了String对象的ArrayList中加入一个File对象,编译器不会产生任何错误提示,而这不是我们想要的。
所以,从Java 5开始,ArrayList在使用时可以加上一个类型参数(type parameter),这个类型参数用来指明ArrayList中的元素类型。类型参数的引入解决了以上提到的两个问题,如以下代码所示:
ArrayList s = new ArrayList();
s.add("abc");
String s = s.get(0); //无需进行强制转换
s.add(123); //编译错误,只能向其中添加String对象
...
在以上代码中,编译器“获知”ArrayList的类型参数String后,便会替我们完成强制类型转换以及类型检查的工作。
2.、泛型类
所谓泛型类(generic class)就是具有一个或多个类型参数的类。例如:
public class Pair {
private T first;
private U second;
public Pair(T first, U second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public U getSecond() {
return second;
}
public void setFirst(T newValue) {
first = newValue;
}
public void setSecond(U newValue) {
second = newValue;
}
}
上面的代码中我们可以看到,泛型类Pair的类型参数为T、U,放在类名后的尖括号中。这里的T即Type的首字母,代表类型的意思,常用的还有E(element)、K(key)、V(value)等。当然不用这些字母指代类型参数也完全可以。
实例化泛型类的时候,我们只需要把类型参数换成具体的类型即可,比如实例化一个Pair
Pair<String, Integer> pair = new Pair<String, Integer>();
点击查看更多……
四、解析XML的几种方式的原理与特点:DOM、SAX、PULL
Android中解析XML用的不多。
SAX
sax是一个用于处理xml事件驱动的“推”模型;
优点:解析速度快,占用内存少,它需要哪些数据再加载和解析哪些内容。
缺点:它不会记录标签的关系,而是需要应用程序自己处理,这样就会增加程序的负担。
DOM
dom是一种文档对象模型;
优点:dom可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构,dom技术使得用户页面可以动态的变化,如动态显示隐藏一个元素,改变它的属性,增加一个元素等,dom可以使页面的交互性大大增强。
缺点:dom解析xml文件时会将xml文件的所有内容以文档树方式存放在内存中。
PULL
pull和sax很相似,区别在于:pull读取xml文件后触发相应的事件调用方法返回的是数字,且pull可以在程序中控制,想解析到哪里就可以停止解析。 (SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。pull是一个while循环,随时可以跳出,而sax不是,sax是只要解析了,就必须解析完成。)
Dom解析案例:
//Xml文件
"1.0" encoding="utf-8" standalone="no"?>
"001">
小明
90
90
93
"002">
小李
78
86
98
"003">
小王
89
83
95
//省略创建Student类相应代码
//创建StudentUtils关键工具类
/**
* Created by softpo
* Time on 14:30.
* Email [email protected]
*/
public class StudentUtils {
private static Document document = null;
private static String path = "src/com/softpo/student.xml";
static {
try {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
document = documentBuilder.parse(path);
} catch (Exception e) {
System.out.println("初始化失败...");
e.printStackTrace();
}
}
/**
* 获取所有学生信息
*
* @return
*/
public static ArrayList readAll() {
ArrayList array = new ArrayList();
NodeList students = document.getElementsByTagName("student");
for (int i = 0; i < students.getLength(); i++) {
Element node_student = (Element) students.item(i);
String id = node_student.getAttribute("sid");
Node node_name = node_student.getElementsByTagName("name").item(0);
String name = node_name.getTextContent();
Element node_course = (Element) node_student.getElementsByTagName("course").item(0);
Node course_java = node_course.getElementsByTagName("java").item(0);
Node course_oracle = node_course.getElementsByTagName("oracle").item(0);
Node course_vb = node_course.getElementsByTagName("vb").item(0);
int score_java = Integer.parseInt(course_java.getTextContent());
int score_oracle = Integer.parseInt(course_oracle.getTextContent());
int score_vb = Integer.parseInt(course_vb.getTextContent());
Student student = new Student(id, name, score_java, score_oracle, score_vb);
array.add(student);
}
return array;
}
/**
* 根据ID获取一个学生的信息
* @param sid
* @return
*/
public static Student getStudentById(String sid) {
NodeList students = document.getElementsByTagName("student");
for (int i = 0; i < students.getLength(); i++) {
Element node_student = (Element) students.item(i);
String id = node_student.getAttribute("sid");
if (!id.equals(sid)) {
continue;
}
Node node_name = node_student.getElementsByTagName("name").item(0);
String name = node_name.getTextContent();
Element node_course = (Element) node_student.getElementsByTagName("course").item(0);
Node course_java = node_course.getElementsByTagName("java").item(0);
Node course_oracle = node_course.getElementsByTagName("oracle").item(0);
Node course_vb = node_course.getElementsByTagName("vb").item(0);
int score_java = Integer.parseInt(course_java.getTextContent());
int score_oracle = Integer.parseInt(course_oracle.getTextContent());
int score_vb = Integer.parseInt(course_vb.getTextContent());
Student student = new Student(id, name, score_java, score_oracle, score_vb);
return student;
}
return null;
}
/**
* 添加学生
*
* @param student
*/
public static void addStudent(Student student) {
Element stu = document.createElement("student");
stu.setAttribute("sid", student.getId());
Element name = document.createElement("name");
name.setTextContent(student.getName());
Element course = document.createElement("course");
Element score_java = document.createElement("java");
Element score_oracle = document.createElement("oracle");
Element score_vb = document.createElement("vb");
score_java.setTextContent(String.valueOf(student.getScore_java()));
score_oracle.setTextContent(String.valueOf(student.getScore_oracle()));
score_vb.setTextContent(String.valueOf(student.getScore_vb()));
course.appendChild(score_java);
course.appendChild(score_oracle);
course.appendChild(score_vb);
stu.appendChild(name);
stu.appendChild(course);
document.getDocumentElement().appendChild(stu);
update(document, path);
}
/**
* 根据ID删除一个学生
*
* @param sid
*/
public static void deleteStudentById(String sid) {
NodeList students = document.getElementsByTagName("student");
for (int i = 0; i < students.getLength(); i++) {
Element student = (Element) students.item(i);
if (student.getAttribute("sid").equals(sid)) {
student.getParentNode().removeChild(student);
}
}
update(document, path);
}
/**
* 更新到文件
*
* @param document
* @param path
*/
public static void update(Document document, String path) {
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(new File(path)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
//主函数
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean flag = true;
while(flag){
// 显示操作界面
System.console();
System.out.println("*********************操作界面*********************");
System.out.println("\t\t1.查询所有学生的成绩");
System.out.println("\t\t2.按照ID查询学生成绩 ");
System.out.println("\t\t3.添加一个学生");
System.out.println("\t\t4.按照ID删除一个学生");
System.out.println("\t\t0.退出系统");
System.out.println("************************************************");
// 获取用户的操作
String operate = scanner.next();
if ("1".equals(operate)) {
ArrayList students = StudentUtils.readAll();
System.out.println("所有的学生信息如下:");
System.out.println("Name\tID\tJava\tOracle\tVB");
for (Student student : students) {
System.out.println(student.getName() + "\t" + student.getId()
+ "\t" + student.getScore_java() + "\t"
+ student.getScore_oracle() + "\t"
+ student.getScore_vb());
}
}else if("2".equals(operate)){
System.out.println("请输入要查询的学生ID:");
String sid = scanner.next();
Student student = StudentUtils.getStudentById(sid);
System.out.println("学号为"+sid+"的学生的信息如下:");
System.out.println("Name\tID\tJava\tOracle\tVB");
System.out.println(student.getName() + "\t" + student.getId()
+ "\t" + student.getScore_java() + "\t"
+ student.getScore_oracle() + "\t"
+ student.getScore_vb());
}else if("3".equals(operate)){
System.out.println("请输入要添加的学生ID:");
String sid = scanner.next();
System.out.println("请输入要添加的学生姓名:");
String name = scanner.next();
System.out.println("请输入要添加的学生Java成绩:");
int score_java = Integer.parseInt(scanner.next());
System.out.println("请输入要添加的学生Oracle成绩:");
int score_oracle = Integer.parseInt(scanner.next());
System.out.println("请输入要添加的学生VB成绩:");
int score_vb = Integer.parseInt(scanner.next());
Student student = new Student(sid, name, score_java, score_oracle, score_vb);
StudentUtils.addStudent(student);
System.out.println("添加成功!");
}else if("4".equals(operate)){
System.out.println("请输入要删除的学生的ID:");
String sid = scanner.next();
StudentUtils.deleteStudentById(sid);
System.out.println("删除成功!");
}
System.out.println("是否继续?(Y/N)");
flag = scanner.next().trim().toLowerCase().equals("y")?true:false;
}
scanner.close();
}
}
未完待续……