Java開發西安地區最近面試彙總(二)

在這裏插入圖片描述

問題1

SQL中delete,truncate,drop的區別

1、刪除表數據

  • DELETE語句執行刪除的過程是每次從表中刪除一行,並且同時將該行的刪除操作作爲事務記錄在日誌中保存以便進行進行回滾操作
  • TRUNCATE TABLE 則一次性地從表中刪除所有的數據,並不把單獨的刪除操作記錄記入日誌保存,刪除行是不能恢復的。無法實現回滾
  • DROP會刪除表的結構所依賴的約束,觸發器,索引,依賴於該表的存儲過程/函數將保留,但是變爲invalid狀態
    truncate與不帶where的delete:只刪除數據,而不刪除表的結構(定義)

2、表和索引所佔空間

  • DELETE:不會減少表或索引所佔用的空間。
  • TRUNCATE :表和索引所佔用的空間會恢復到初始大小,
  • DROP:語句將表所佔用的空間全釋放掉。

3、應用範圍

  • DELETE可以是table和view
  • TRUNCATE 只能對table
  • DROP 可以刪除表、視圖、索引、過程、函數等

4、運行速度
drop > truncate > delete

問題2

索引的作用

  • 通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性
  • 大大加快數據的檢索速度
  • 加快表與表之間的連接,在實現數據的參考完整性方面特別有意義
  • 在使用分組和排序,子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間
  • 通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能

問題3

mybatis中resultType和resultMap的區別

MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,resultType是直接表示返回類型的,而resultMap則是對外部ResultMap的引用,但是resultType跟resultMap不能同時存在。在MyBatis進行查詢映射的時候,其實查詢出來的每一個屬性都是放在一個對應的Map裏面的,其中鍵是屬性名,值則是其對應的值。當提供的返回類型屬性是resultType的時候,MyBatis會將Map裏面的鍵值對取出賦給resultType所指定的對象對應的屬性。所以其實MyBatis的每一個查詢映射的返回類型都是ResultMap,只是當我們提供的返回類型屬性是resultType的時候,MyBatis對自動的給我們把對應的值賦給resultType所指定對象的屬性,而當我們提供的返回類型是resultMap的時候,因爲Map不能很好表示領域模型,我們就需要自己再進一步的把它轉化爲對應的對象,這常常在複雜查詢中很有作用。

問題4

InnoDB和MyISAM的區別

  1. 事務支持
    MyISAM不支持事務,而InnoDB支持。InnoDB的AUTOCOMMIT默認是打開的,即每條SQL語句會默認被封裝成一個事務,自動提交,這樣會影響速度,所以最好是把多條SQL語句顯示放在begin和commit之間,組成一個事務去提交。
  2. 表鎖差異
    MyISAM:只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert併發的情況下,可以在表的尾部插入新的數據。
    InnoDB:行級鎖,是innodb的最大特色。行鎖大幅度提高了多用戶併發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的
  3. CURD操作
    MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。
    InnoDB:如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE 從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數據的表,最好使用truncate table這個命令。
  4. 存儲
    MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型, .frm文件存儲表定義,數據文件的擴展名爲.MYD, 索引文件的擴展名是.MYI
    InnoDB,基於磁盤的資源是InnoDB表空間數據文件和它的日誌文件,InnoDB 表的大小隻受限於操作系統文件的大小
    注意:MyISAM表是保存成文件的形式,在跨平臺的數據轉移中使用MyISAM存儲會省去不少的麻煩
  5. 全文索引
    MyISAM:支持(FULLTEXT類型的)全文索引
    InnoDB:不支持(FULLTEXT類型的)全文索引,但是innodb可以使用sphinx插件支持全文索引,並且效果更好。
  6. 併發
    MyISAM讀寫互相阻塞:不僅會在寫入的時候阻塞讀取,MyISAM還會在讀取的時候阻塞寫入,但讀本身並不會阻塞另外的讀
    InnoDB 讀寫阻塞與事務隔離級別相關
  7. 外鍵
    MyISAM:不支持
    InnoDB:支持

問題5

數據庫中模糊查詢命令like有兩個通配符”%”和”_”的區別

數據庫中模糊查詢命令like有兩個通配符”%”和”_”,其中:
%匹配0或多個字符
_匹配任意1個字符(必須有一個)

SQL>  create table tt ( name char(10) );
SQL>  insert into tt values ( '1234' );
SQL>  select * from tt where name like '_23%';
 NAME
----------
1234
SQL> select * from tt where name like '_1234%' ;
no rows selected  

問題6

js中= =和===的區別

雙等號
  (1)如果兩個值類型相同,再進行三個等號(===)的比較
  (2)如果兩個值類型不同,也有可能相等,需根據以下規則進行類型轉換在比較:
    1)如果一個是null,一個是undefined,那麼相等
    2)如果一個是字符串,一個是數值,把字符串轉換成數值之後再進行比較
三等號
  (1)如果類型不同,就一定不相等
  (2)如果兩個都是數值,並且是同一個值,那麼相等;如果其中至少一個是NaN,那麼不相等。(判斷一個值是否是NaN,只能使用isNaN( ) 來判斷)
  (3)如果兩個都是字符串,每個位置的字符都一樣,那麼相等,否則不相等。
  (4)如果兩個值都是true,或是false,那麼相等
  (5)如果兩個值都引用同一個對象或是函數,那麼相等,否則不相等
  (6)如果兩個值都是null,或是undefined,那麼相等

問題7

CSS選擇器有哪些?哪些屬性可以繼承?

一,css選擇器:
  1.id選擇器( # myid)
  2.類選擇器(.myclassname)
  3.標籤選擇器(div, h1, p)
  4.相鄰選擇器(h1 + p)
  5.子選擇器(ul > li)
  6.後代選擇器(li a)
  7.通配符選擇器( * )
  8.屬性選擇器(a[rel = “external”])
  9.僞類選擇器(a:hover, li:nth-child)

二,繼承問題:
  * 可繼承的樣式: font-size font-family color, UL LI DL DD DT;
  * 不可繼承的樣式:border padding margin width height ;
css繼承特性主要是指文本方面的繼承,盒模型相關的屬性基本沒有繼承特性。

問題8

線程池的創建方式

1、使用ThreadPoolExecutor類(自定義)
2、使用Executors類(工具類)

//創建使用單個線程的線程池
ExecutorService es1 = Executors.newSingleThreadExecutor();
//創建使用固定線程數的線程池
ExecutorService es2 = Executors.newFixedThreadPool(3);
//創建一個會根據需要創建新線程的線程池
ExecutorService es3 = Executors.newCachedThreadPool();

問題9

線程池底層實現的7大重要參數

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  • corePoolSize:線程池中常駐核心線程數
    在創建了線程池後,當有請求任務來之後,就會安排池中的線程去執行請求任務
    當線程池的線程數達到corePoolSize後,就會把到達的任務放到緩存隊列當中
  • maximumPoolSize:線程池能夠容納同時執行的最大線程數,必須大於等於1
  • keepAliveTime:多餘的空閒線程的存活時間
    當前線程池數量超過corePoolSize時,檔口空閒時間達到keepAliveTime值時,多餘空閒線程會被銷燬到只剩下corePoolSize個線程爲止
  • unit:keepAliveTime的單位
  • workQueue:任務隊列,被提交但尚未被執行的任務
  • threadFactory:表示生成線程池中工作線程的線程工廠,用於創建線程一般用默認的即可
  • handler:拒絕策略,表示當隊列滿了並且工作線程大於等於線程池的最大線程數(maximumPoolSize)時如何來拒絕請求執行的runable的策略

問題10

線程池的拒絕策略

jdk內置的四種拒絕策略如下:

  • AbortPolicy策略:該策略會直接拋出異常,阻止系統正常工作。
  • CallerRunsPolicy策略:只要線程池未關閉,該策略直接在調用者線程中,運行當前被丟棄的任務。這樣不會丟棄任務,但是,任務提交線程的性能有可能急劇下降
  • DiscardOldestPolicy策略:該策略將丟棄最老的一個請求,也就是即將被執行的一個任務,並嘗試再次提交當前任務。
  • DiscardPolicy策略:該策略默默的丟棄無法處理的任務,不予任何處理

問題11

vue實例的生命週期

在這裏插入圖片描述

結合生命週期理解鉤子函數

在這裏插入圖片描述

  • 創建期間的生命週期函數:
    • beforeCreate:實例剛在內存中被創建出來,此時,還沒有初始化好 data 和 methods 屬性
    • created實例已經在內存中創建好,此時 data 和 methods 已經創建好,此時還沒有開始編譯模板
    • beforeMount:此時已經完成了模板的編譯,但是還沒有掛載到頁面中
    • mounted:此時,已經將編譯好的模板,掛載到了頁面指定的容器中顯示
  • 運行期間的生命週期函數:
    • beforeUpdate:狀態更新之前執行此函數, 此時 data 中的狀態值是最新的,但是界面上顯示的數據還是舊的,因爲此時還沒有開始重新渲染DOM節點
    • updated:實例更新完畢之後調用此函數,此時 data 中的狀態值 和 界面上顯示的數據,都已經完成了更新,界面已經被重新渲染好了!
  • 銷燬期間的生命週期函數:
    • beforeDestroy:實例銷燬之前調用。在這一步,實例仍然完全可用
    • destroyed:Vue 實例銷燬後調用。調用後,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷燬。

問題12

Java8 中通過 Stream 對列表進行去重的方法

  • 使用distinct()
  • 使用filter()
package test33;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

public class Demo {
    public static void main(String[] args) throws JsonProcessingException {
        //對List<String>去重
        test1();
        System.out.println("=========");
        //對List<Bean>去重
        test2();
        System.out.println("=========");
        //根據Bean中的某個字段值對List<Bean>去重
        test3();
        System.out.println("=========");
        //使用filter去重,按原順序去重
        test4();
        System.out.println("=========");
    }



    private static void test1() {
        List<String> stringList = new ArrayList<String>() {{
            add("A");
            add("A");
            add("B");
            add("B");
            add("C");
        }};
        System.out.print("去重前:");
        for (String s : stringList) {
            System.out.print(s);
        }
        System.out.println();
        stringList = stringList.stream().distinct().collect(Collectors.toList());
        System.out.print("去重後:");
        for (String s : stringList) {
            System.out.print(s);
        }
        System.out.println();
    }
    private static void test2() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        // 1. 對於 Student 列表去重
        List<Student> studentList = getStudentList();
        System.out.print("去重前:");
        System.out.println(objectMapper.writeValueAsString(studentList));
        studentList = studentList.stream().distinct().collect(Collectors.toList());
        System.out.print("去重後:");
        System.out.println(objectMapper.writeValueAsString(studentList));
    }

    private static void test3() throws JsonProcessingException {
        // 這裏第一種方法我們通過新創建一個只有不同元素列表來實現根據對象某個屬性去重
        ObjectMapper objectMapper = new ObjectMapper();
        List<Student> studentList = getStudentList();

        System.out.print("去重前        :");
        System.out.println(objectMapper.writeValueAsString(studentList));
        studentList = studentList.stream().distinct().collect(Collectors.toList());
        System.out.print("distinct去重後:");
        System.out.println(objectMapper.writeValueAsString(studentList));
        // 這裏我們引入了兩個靜態方法,以及通過 TreeSet<> 來達到獲取不同元素的效果
        // 1. import static java.util.stream.Collectors.collectingAndThen;
        // 2. import static java.util.stream.Collectors.toCollection;
        studentList = studentList.stream().collect(
                collectingAndThen(
                        toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new)
        );
        System.out.print("根據名字去重後 :");
        System.out.println(objectMapper.writeValueAsString(studentList));
    }


    public static void test4() throws JsonProcessingException {
        // 這裏第二種方法我們通過過濾來實現根據對象某個屬性去重
        ObjectMapper objectMapper = new ObjectMapper();
        List<Student> studentList = getStudentList();

        System.out.print("去重前        :");
        System.out.println(objectMapper.writeValueAsString(studentList));
        studentList = studentList.stream().distinct().collect(Collectors.toList());
        System.out.print("distinct去重後:");
        System.out.println(objectMapper.writeValueAsString(studentList));
        // 這裏我們將 distinctByKey() 方法作爲 filter() 的參數,過濾掉那些不能加入到 set 的元素
        studentList = studentList.stream().filter(distinctByKey(Student::getName)).collect(Collectors.toList());
        System.out.print("根據名字去重後 :");
        System.out.println(objectMapper.writeValueAsString(studentList));
    }
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }
    private static List<Student> getStudentList() {
        List<Student> studentList = new ArrayList<>();
        Student student1 = new Student() {{
            setStuNo("001");
            setName("Tom");
        }};
        Student student2 = new Student() {{
            setStuNo("002");
            setName("Mike");
        }};
        Student student3 = new Student() {{
            setStuNo("003");
            setName("Tom");
        }};
        Student student4 = new Student() {{
            setStuNo("004");
            setName("Julia");
        }};
        Student student5 = new Student() {{
            setStuNo("005");
            setName("Lily");
        }};

        Student student6 = new Student() {{
            setStuNo("001");
            setName("Kobe");
        }};

        studentList.add(student1);
        studentList.add(student2);
        studentList.add(student1);
        studentList.add(student3);
        studentList.add(student4);
        studentList.add(student3);
        studentList.add(student5);
        studentList.add(student4);
        studentList.add(student5);
        studentList.add(student2);

        studentList.add(student6);

        return studentList;
    }
}
package test33;

public class Student {
    private String stuNo;
    private String name;

    public String getStuNo() {
        return stuNo;
    }

    public void setStuNo(String stuNo) {
        this.stuNo = stuNo;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

在這裏插入圖片描述

問題13

Mybatis一對多映射

https://www.cnblogs.com/yinzhengjie/p/9287306.html

問題14

一個線程的生命週期有哪幾種狀態?它們之間如何流轉的?

  • NEW:毫無疑問表示的是剛創建的線程,還沒有開始啓動。
  • RUNNABLE: 表示線程已經觸發 **start()**方式調用,線程正式啓動,線程處於運行中狀態。
  • BLOCKED:表示線程阻塞,等待獲取鎖,如碰到 synchronized、lock 等關鍵字等佔用臨界區的情況,一旦獲取到鎖就進行 RUNNABLE 狀態繼續運行。
  • WAITING:表示線程處於無限制等待狀態,等待一個特殊的事件來重新喚醒,如通過wait()方法進行等待的線程等待一個 notify()或者 notifyAll()方法,通過 join()方 法進行等待的線程等待目標線程運行結束而喚醒,一旦通過相關事件喚醒線程,線 程就進入了 RUNNABLE 狀態繼續運行。
  • TIMED_WAITING:表示線程進入了一個有時限的等待,如 sleep(3000),等待 3 秒 後線程重新進行 RUNNABLE 狀態繼續運行。
  • TERMINATED:表示線程執行完畢後,進行終止狀態。需要注意的是,一旦線程 通過 start 方法啓動後就再也不能回到初始 NEW 狀態,線程終止後也不能再回到 RUNNABLE 狀態
    在這裏插入圖片描述

問題15

Callable,Runnable,Future

Callable,Runnable

兩者最大的不同點是:

  • 實現Callable接口的任務線程能返回執行結果;而實現Runnable接口的任務線程不能返回結果;
  • Callable接口的call()方法允許拋出異常;而Runnable接口的run()方法的異常只能在內部消化,不能繼續上拋;

在這裏插入圖片描述

FutureTask和Future:

Callable功能更強大一些,被線程執行後,可以返回值,這個返回值可以被Future拿到,也就是說,Future可以拿到異步執行任務的返回值
Future
接口,用於獲得任務的執行結果。
Future的get方法獲取結果只有在計算完成時獲取,否則會一直阻塞直到任務轉入完成狀態,然後會返回結果或者拋出異常。
FutureTask
實現類,實現了RunnableFuture接口,而RunnableFuture同時繼承Runnable和Future接口,即FutureTask是Runnable和Future的實現類。可使用FutureTask包裝Callable或Runnable對象。

問題16

Spring的作用

Spring Framework即Spring輕量級企業開發框架,提供了從表現層到業務層再到持久層的一套完整的解決方案。我 們在項目中可以只使用 spring 一個框架,就可以提供表現層的 mvc 框架,持久層的 Dao 框架。它的兩大核心 IoC 和 AOP 更是爲我們程序解耦和代碼簡潔易維護提供了支持。

問題17

經常使用的註解

  • 聲明bean的註解
    @Component 組件,沒有明確的角色
    @Service 在業務邏輯層使用(service層)
    @Repository 在數據訪問層使用(dao層)
    @Controller 在展現層使用,控制器的聲明(C)
  • 注入bean的註解
    @Autowired:由Spring提供
    @Inject:由JSR-330提供
    @Resource:由JSR-250提供
    都可以註解在set方法和屬性上,推薦註解在屬性上(一目瞭然,少寫代碼)。
  • java配置類相關注解
    @Configuration 聲明當前類爲配置類,相當於xml形式的Spring配置(類上)
    @Bean 註解在方法上,聲明當前方法的返回值爲一個bean,替代xml中的方式(方法上)
    @ComponentScan 用於對Component進行掃描,相當於xml中的(類上)
    @WishlyConfiguration 爲@Configuration與@ComponentScan的組合註解,可以替代這兩個註解
  • 切面(AOP)相關注解
    Spring支持AspectJ的註解式切面編程。
    @Aspect 聲明一個切面(類上) 使用@After、@Before、@Around定義建言(advice),可直接將攔截規則(切點)作爲參數。
    @After 在方法執行之後執行(方法上)
    @Before 在方法執行之前執行(方法上)
    @Around 在方法執行之前與之後執行(方法上)
    @PointCut 聲明切點 在java配置類中使用@EnableAspectJAutoProxy註解開啓Spring對AspectJ代理的支持(類上)
  • @Bean的屬性支持
    @Scope 設置Spring容器如何新建Bean實例(方法上,得有@Bean) 其設置類型包括:
    Singleton (單例,一個Spring容器中只有一個bean實例,默認模式),
    Protetype (每次調用新建一個bean),
    Request (web項目中,給每個http request新建一個bean),
    Session (web項目中,給每個http session新建一個bean),
    GlobalSession(給每一個 global http session新建一個Bean實例)
    @StepScope 在Spring Batch中還有涉及
    @PostConstruct 由JSR-250提供,在構造函數執行完之後執行,等價於xml配置文件中bean的initMethod
    @PreDestory 由JSR-250提供,在Bean銷燬之前執行,等價於xml配置文件中bean的destroyMethod
  • @Value註解
    @Value 爲屬性注入值(屬性上)
  • SpringMVC部分
    @EnableWebMvc 在配置類中開啓Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,若無此句,重寫WebMvcConfigurerAdapter方法(用於對SpringMVC的配置)。
    @Controller 聲明該類爲SpringMVC中的Controller
    @RequestMapping 用於映射Web請求,包括訪問路徑和參數(類或方法上)
    @ResponseBody 支持將返回值放在response內,而不是一個頁面,通常用戶返回json數據(返回值旁或方法上)
    @RequestBody 允許request的參數在request體中,而不是在直接連接在地址後面。(放在參數前)
    @PathVariable 用於接收路徑參數,比如@RequestMapping(“/hello/{name}”)申明的路徑,將註解放在參數中前,即可獲取該值,通常作爲Restful的接口實現方法。
    @RestController 該註解爲一個組合註解,相當於@Controller和@ResponseBody的組合,註解在類上,意味着,該Controller的所有方法都默認加上了@ResponseBody。
    @ControllerAdvice 通過該註解,我們可以將對於控制器的全局配置放置在同一個位置,註解了@Controller的類的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute註解到方法上, 這對所有註解@RequestMapping的控制器內的方法有效。
    @ExceptionHandler 用於全局處理控制器裏的異常
    @InitBinder 用來設置WebDataBinder,WebDataBinder用來自動綁定前臺請求參數到Model中。
    @ModelAttribute 本來的作用是綁定鍵值對到Model裏,在@ControllerAdvice中是讓全局的@RequestMapping都能獲得在此處設置的鍵值對。

問題18

java8中map的新特性

對map集合排序,根據key或者value操作排序(升序、降序)
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章