1. 程式人生 > >面試心得與總結(二)

面試心得與總結(二)

程式設計師大部分時間都是在解決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<People> pClass = People.class;
        System.out.println(pClass);
        try {
            Constructor<People> 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<String> s = new ArrayList<String>();
s.add("abc");
String s = s.get(0); //無需進行強制轉換
s.add(123);  //編譯錯誤,只能向其中新增String物件
...

在以上程式碼中,編譯器“獲知”ArrayList的型別引數String後,便會替我們完成強制型別轉換以及型別檢查的工作。

2.、泛型類

所謂泛型類(generic class)就是具有一個或多個型別引數的類。例如:

public class Pair<T, U> {
    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檔案
<?xml version="1.0" encoding="utf-8" standalone="no"?><students>
    <student sid="001">
        <name>小明</name>
        <course>
            <java>90</java>
            <oracle>90</oracle>
            <vb>93</vb>
        </course>
    </student>
    <student sid="002">
        <name>小李</name>
        <course>
            <java>78</java>
            <oracle>86</oracle>
            <vb>98</vb>
        </course>
    </student>
    <student sid="003">
        <name>小王</name>
        <course>
            <java>89</java>
            <oracle>83</oracle>
            <vb>95</vb>
        </course>
    </student>
</students>

//省略建立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<Student> readAll() {
        ArrayList<Student> array = new ArrayList<Student>();
        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<Student> 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();
    }
}

未完待續……

相關推薦

面試心得總結

程式設計師大部分時間都是在解決Bug,當我解決Bug時,總有一種隱隱的感覺,感覺我在尋找迷宮的入口。 我圍著迷宮一直轉圈,每轉一圈,對他越熟悉,越瞭解,就越接近入口。好比最近的非常火的美劇《西部世界》,機器人死千百次,每次都是重複,每次重複都不一樣,

面試心得總結

找工作一定要做好Homework,認準準備筆試和麵試,認真研究你投簡歷的公司 如果你能給應聘公司提出建議,指出他們公司產品的不足,可以改進的地方,那應聘成功的機率就回提高 之前有朋友分析了某個公司的Android客戶端App,寫了一份郵

java面試基礎知識總結

五、Object 通用方法 equals()方法 等價關係 Ⅰ 自反性 x.equals(x); // true Ⅱ 對稱性 x.equals(y) == y.equals(x); // true Ⅲ 傳遞性 if (x.equals(y)

工作一年多的感慨總結

前言   前一篇(工作一年多的感慨與總結(一))算是對自己對這一年不如意的地方的一些抱怨與吐槽吧,那麼今天這一篇就總結記錄下那些正能量的事吧(自己能把自己感動的故事),廢話不多說,趁著有足夠的時間回憶,抓緊記錄! 2018/7-2018/9  跳槽準備 (1)人總是要有點資本的   其實從當時的公司入職

機器學習筆試面試超詳細總結

51、概率和資訊量的關係 示例: 符號集 a 、 b 、 c 、 d ,它們相互獨立,相應概率為 1/2 、 1/4 、 1/8/ 、 1/16 ,其中包含資訊量最小的符號(a) 解析: 訊息出現的概率越小,說明限制條件越多,則訊息中所包含的資訊量就越大;

Java Web 學習總結Servlet核心介面+Servlet3.0配置

  Servlet3.0版本對Servlet配置進行了重大變革,Servlet類不需要再麻煩的去編輯web.xml檔案了,只需要在類上面進行註釋就可以了,獲得了 Java 社群的一片讚譽之聲,以下是新增的註解支援。 @WebServlet @WebServlet 用於將一個類宣告為 Servlet,該註解

運維工程師面試筆試題總結

1、Linux啟動大致過程? 1)POST:通電自檢 2)BIOS:BOIS自檢,載入硬碟 3)讀取MBR,進行MBR引導 4)grub引導選單 5)載入核心 Kernel(ramdisk) 6)啟動init程序,依據inittab檔案設定執行級別 7)init程序,執行rc.sysin

java web學習心得總結1——jsp基本語法

java web自學快三個月了,前面的基礎知識都忘了,以後每天寫一篇部落格總結一下. 或者關注下我的新浪微博:Mr翅膀君 一.page指令 1.language屬性 <%@ page language="java" import="java.util.*" page

C++ STL開發溫習總結: 2.C++儲存技術

 C++ STL開發溫習與總結(二):2.C++儲存技術       使用了多年C++,沒有系統的溫習總結過,所以準備溫習《C++STL程式設計師開發指南》,本系列篇章將會是溫習總結該書本概念和技術。       本節討論的C++儲存技術保局哦C++儲存型別,C++儲存

Spring核心探索總結:Spring容器初始化原始碼探索

Spring容器概述 容器是spring的核心,Spring容器使用DI管理構成應用的元件,它會建立相互協作的元件之間的關聯,負責建立物件,裝配它們,配置它們並管理它們的生命週期,從生存到死亡(在這裡,可能就是new 到 finalize())。 Sprin

JAVA大資料面試總結

Java基礎知識 Java中常用演算法:冒泡、選擇、快速 冒泡:兩兩比較,每一輪(0~length-i)挑出一個最值,並將其移除,迴圈遍歷1~length   選擇:外面定義從0~length-1,先選定一個最先面的下目標作為最小下標,將其所對應的值逐一與其他比較,如果

針對《面試心得總結—BAT、網易、蘑菇街》一文中出現的技術問題的收集整理2

16. Java面向物件的三個特徵與含義 1 . 封裝性   將物件的狀態資訊儘可能的隱藏在物件內部,只保留有限的介面和方法與外界進行互動,從而避免了外界對物件內部屬性的破壞。   Java中使用訪問控制符來保護對類、變數、方法和構造方法的訪問 2. 繼承    java通

Echarts使用心得總結——非同步資料載入更新

上次用Echarts做了一個會員增量統計圖表,正好用到了Echarts非同步資料載入,使用的是下拉聯動+Echarts資料更新,下面把實現程式碼分享給大家。 一、時間選擇器下拉聯動的實現: <div class="selects-div"> <

針對《面試心得總結—BAT、網易、蘑菇街》一文中出現的技術問題的收集整理3

JVM 1. 記憶體模型以及分割槽,需要詳細到每個區放什麼 JVM記憶體區域模型 1.方法區 也稱”永久代” 、“非堆”,  它用於儲存虛擬機器載入的類資訊、常量、靜態變數、是各個執行緒共享的記憶體區域。預設最小值為16MB,最大值為64MB,可以通過-X

java 面試基礎總結---多線程

future sync 一個 副本 void all call ava task 1、實現多線程的三種方法 1.繼成Thread 類,覆蓋run()方法即可 2.implements Runnable接口 3.implements Callale接口,執行時通過Future

Python的語言基礎總結之循環字符串操作

整數 範圍 輸入 IV 字符串 spl 余額 upper ict 一、循環和分支   1.  條件分支語句   if  條件:     代碼塊   else:     代碼塊   2.  循環語句之while   思考1:求1+2+3+....+10的值    sum =

關於Java基礎的複習總結運算子控制結構&程式設計師節的留影

大夢誰先覺,平生我自知。 每次醒來之後,說一句,感覺自己要去拯救蒼生,哈哈。 末尾放上程式設計師節的照片,帶人的就不放了,醜(* ̄rǒ ̄)。 1、變數的宣告和賦值 資料型別 變數名=值; 2、型別轉換 自動型別轉換 強制型別轉換 byte short int long float

JAVA面試常問知識總結

JAVA中的引數傳遞總結先看兩道筆試題: 1 public class Test2 { 2 3 public static void main (String [] args) { 4 StringBuffer a = new StringBuff

面試總結

百度一面: 1、多型、如何實現、虛擬函式的實現及其作用?哪些可以為虛擬函式,哪些必須,哪些不可以?虛擬函式內部是怎麼實現的? 多型:允許將父物件設定成和一個或多個子物件相等;也就是允許將子類型別的指標賦值給父類型別的指標(一個介面,多種方法,即介面重用);不論傳遞過來的究竟是哪個類的物件,函

1109_Solr學習總結Solr的安裝配置

Solr學習總結(二)Solr的安裝與配置 接著前一篇,這裡總結下Solr的安裝與配置     1.準備     1.安裝Java8 和 Tomcat9 ,java和tomcat 的安裝這裡不再重複。需要注意的是這兩個的版本相容問題。貌似java8 不支援,tomcat7