Day28 Java SE总复习

知识结构体系图

这里写图片描述

基础知识部分

1.Java跨平台原理(字节码文件、虚拟机)

这里写图片描述
C/C++语言都直接编译成针对特定平台机器码。如果要跨平台,需要使用相应的编译器重新编译。

2) Java源程序(.java)要先编译成与平台无关的字节码文件(.class),然后字节码文件再解释成机器码运行。解释是通过Java虚拟机来执行的。
3) 字节码文件不面向任何具体平台,只面向虚拟机。
4) Java虚拟机是可运行Java字节码文件的虚拟计算机。不同平台的虚拟机是不同的,但它们都提供了相同的接口。
5) Java语言具有一次编译,到处运行的特点。就是说编译后的.class可以跨平台运行,前提是该平台具有相应的Java虚拟机。但是性能比C/C++要低。
6) Java的跨平台原理决定了其性能没有C/C++高
这里写图片描述

2.&和&&的区别和联系,|和||的区别和联系

&和&&的联系(共同点):
&和&&都可以用作逻辑与运算符(and)。
当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要有一方为false,结果都为false。
逻辑运算的结果是相同的。
&和&&的区别(不同点):
(1)、&逻辑运算符称为逻辑与运算符,&&逻辑运算符称为短路与运算符。
对于&:无论任何情况,&两边的操作数或表达式都会参与计算。
对于&&:当&&左边的操作数为false或左边表达式结果为false时,&&右边的操作数或表达式将不参与计算,此时最终结果都为false。
综上所述,如果逻辑与运算的第一个操作数是false或第一个表达式的结果为false时,对于第二个操作数或表达式是否进行运算,对最终的结果没有影响,结果肯定是false。
推介平时多使用&&,因为它效率更高些。
(2)&还可以用作位运算符。当&两边操作数或两边表达式的结果不是boolean类型时,&用于按位与运算符的操作。
|和||的区别和联系与&和&&的区别和联系类似

/**
 * &&短路与   & 逻辑与
 */
public class Test1 {
    public static void main(String[] args) {
        //如果第一个操作数是真,右边都运算
        boolean flag1 = 5<6  && 7==8; // 左右都运算
        boolean flag2 = 5<6  & 7==8;  // 左右都运算
        //如果第一个操作数是假,结果已经确定肯定是false,&&右边不参与运行(短路)
        boolean flag3 = 5>6  && 7==8; // 右边不运算
        boolean flag4 = 5>6  & 7==8;  // 左右都运算

        //建议采用&&,性能高
        //注意:使用&&或者&,对最终逻辑运算的结果没有影响,
        //但是对右边表达式中变量的结果可能有影响
        int i =5;
        boolean flag5 = 5>6 && 6>i++;
        boolean flag6 = 5>6 & 6>i++;

        //&还是逻辑运算符
        //int n1 = 5&&6;
        int n2 = 5 & 6;  //&此时是位运算符
        System.out.println(n2);//4
    }
}
3.switch条件变量的取值类型

byte short int
char
不可以是float、double
不可以是布尔
不可以是long
可以是枚举吗?JDK1.5之前不可以,之后(包含1.5)可以
可以是String吗?JDK1.7之前不可以,之后(包含1.7)可以

对应包装类是否可以:其实还是自动拆箱了。包装类本身是不可以的。

enum Season {
    春,夏,秋,冬
}
public class Test2 {
    public static void main(String[] args) {
        int n=5;
        byte b = 6;
        short s = 7;
        long l = 8;//不可以
        char  ch ='A';
        boolean flag = false;//不可以
        float f = 5.6f; //不可以
        double d = 5.6;//不可以
        String str = "abc";//JDK1.7可以的
        Season season = Season.冬;//JDK1.5可以

        Integer in = new Integer(5);
        switch(in){         
        }
    }
}
4.递归
1.基础示例:求n! ,斐波那契数列
2.某些查找算法,比如折半查找
3.某些排序算法,比如归并和快速排序
4.复制/删除文件夹(包括子文件夹)  统计所学代码行数
5.二叉树的遍历、图的深度优先遍历
6.字符全排列、字符回文   
5.查找和排序

顺序表的查找:顺序查找O(n)、折半查找O(log2n)
树的查找:二叉查找树、二叉平衡树 O(log2n)
哈希表的查找 O(1) 与上面两种查找,最大的不同是不需要通过比较,而是通过计算就可以直接定位元素位置
按照索引查找 顺序表 O(1) 链表 O(n)

查看之前讲解的四种排序的的代码和视频,此处不再重复
强调:
这里写图片描述
1.直接插入排序、简单选择排序、冒泡排序是最简单的三种排序算法,时间复杂度也最高O(n2),作为基础排序,面试中有被问到,三种都要掌握。
2.三种简单排序算法简单,但是效率低下;高级排序在简单排序基础上优化,算法复杂,换取的是性能提高,同时可能需要更多的辅助空间。
3.快速排序和归并排序都使用了分治和递归,所以面试时被问到的机会比较高,尤其是快速排序。
4.从时间性能上看,快速排序是所有排序算法中实际性能最好的,然而快速排序在最坏情况下(数据基本有序)的时间性能不如堆排序和归并排序,
并且空间复杂度高,所以更适合数据不大的情况。
5.基于比较的排序的时间复杂度下限是 Ω(nlogn),即这已经是最高的效率了。
6.如果在面试中有面试官要求你写一个O(n)时间复杂度的排序算法,你千万不要立刻说:这不可能!
使用非比较的排序(计数排序、基数排序)可以达到线性时间O(n)复杂度的排序,
只不过有前提条件,就是待排序的数要满足一定的范围的整数,而且可能需要较多辅助空间。
7.需要结合具体的需求和场景来选择甚至组合使用。才能达到高效稳定的目的。没有最好的排序,只有最适合的排序。

面向对象部分

1.类和对象

类是对象的抽象,而对象是类的具体实例。
类是抽象的,不占用内存,而对象是具体的,占用存储空间。
类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
类和对象好比图纸和实物的关系,模具和铸件的关系。

比如人类就是一个概念,人类具有身高,体重等属性。人类可以做吃饭、说话等方法。
小明就是一个具体的人,也就是实例,他的属性是具体的身高200cm,体重180kg,他做的方法是具体的吃了一碗白米饭,说了“12345”这样一句话。

比如英雄是类
名称、性别、生命值、移动的速度、攻击的速度、拥有的物品是属性
移动、攻击、升级、购买/出售/使用物品是方法。
具体的英雄是对象。

2.方法重写方法重载

这里写图片描述

3.static关键字的作用(修饰变量、方法、代码块、内部类,不可以修饰构造方法)

static可以修饰变量、方法、代码块和内部类
1. static属性属于这个类所有,即由该类创建的所有对象共享同一个static属性。可以对象创建后通过对象名.属性名和类名.属性名两种方式来访问。也可以在没有创建任何对象之前通过类名.属性名的方式来访问。
static变量和非static变量的区别(都是成员变量,不是局部变量)
(1)在内存中份数不同(水杯和饮水机)
不管有多少个对象,static变量只有1份。对于每个对象,实例变量都会有单独的一份
static变量是属于整个类的,也称为类变量。而非静态变量是属于对象的,也称为实例变量
(2)在内存中存放的位置不同
静态变量存在方法区中, 实例变量存在堆内存中 *
(3)访问的方式不同
实例变量: 对象名.变量名 stu1.name=”小明明”;
静态变量:对象名.变量名 stu1.schoolName=”西二旗小学”; 不推荐如此使用
类名.变量名 Student.schoolName=”东三旗小学”; 推荐使用
(4)在内存中分配空间的时间不同
实例变量:创建对象的时候才分配了空间。静态变量:第一次使用类的时候
Student.schoolName=”东三旗小学”;或者Student stu1 = new Student(“小明”,”男”,20,98);
2. static方法也可以通过对象名.方法名和类名.方法名两种方式来访问
3. static代码块。当类被第一次使用时(可能是调用static属性和方法,或者创建其对象)执行静态代码块,且只被执行一次,主要作用是实现static属性的初始化。
4. static内部类:属于整个外部类,而不是属于外部类的每个对象。不能访问外部类的非静态成员(变量或者方法),可以访问外部类的静态成员
这里写图片描述

4.三大特征(封装、继承、多态)

1.private/默认/protected/public权限修饰符的区别
2.方法重载和方法重写的区别
3.继承条件下构造方法的执行过程(第一条默认是super(),可以改写为this(…)、super(…))
4.写出java.lang.Object类的六个常用方法及其作用
5.多态的含义、前提(三个)、内容(向上向下转型)和应用(使用父类做方法形参)

5.接口和抽象类的区别和联系

相同点
Ø 抽象类和接口均包含抽象方法(注意:抽象类也可以没有一个抽象方法),类必须实现所有的抽象方法,否则是抽象类
Ø 抽象类和接口都不能实例化
Ø 他们位于继承树的顶端,用来被其他类继承和实现
两者的区别主要体现在两方面:语法方面和设计理念方面
语法方面的区别是比较低层次的,非本质的,主要表现在:
Ø 成员变量:接口中只能定义全局静态常量public static final ,不能定义变量。抽象类中可以定义常量和变量。
Ø 成员方法:接口中所有的方法都是全局抽象方法public abstract 。抽象类中可以有0个、1个或多个,甚至全部都是抽象方法。
Ø 构造方法:抽象类中可以有构造方法,但不能用来实例化,而在子类实例化是执行,完成属于抽象类的初始化操作。接口中不能定义构造方法。
Ø 单继承多实现:一个类只能有一个直接父类(可以是抽象类),但可以同时实现多个接口。
一个类使用extends来继承抽象类,使用implements来实现接口。
二者的主要区别还是在设计理念上,其决定了某些情况下到底使用抽象类还是接口。
Ø 抽象类体现了一种继承关系,目的是复用代码,抽象类中定义了各个子类的相同代码,可以认为父类是一个实现了部分功能的“中间产品”,而子类是“最终产品”。父类和子类之间必须存在“is-a”的关系,即父类和子类在概念本质上应该是相同的。
Ø 接口并不要求实现类和接口在概念本质上一致的,仅仅是实现了接口定义的约定或者能力而已。接口定义了“做什么”,而实现类负责完成“怎么做”,体现了功能(规范)和实现分离的原则。接口和实现之间可以认为是一种“has-a的关系”
举例

Bird extends Animal
Bird/Plane implements Flyable
Bird/Product/News/Course implements Comparable、Comparator

抽象类:InputStream OutputStream Reader Writer DateFormat
接口:Comparable Comparator Serializable List Set Map Collection Iterator Runnable Callable

JDK1.8之后接口也可以有非抽象方法

字符串相关

1.String、StringBuffer、StringBuilder的联系和区别

阅读String、StringBuffer、StringBuilder的源码,说明底层原理

2.分析下面的Java程序,编译运行后的输出结果是( )。

public class Example {
String str = new String(“good”);
char[] ch = { ‘a’, ‘b’, ‘c’ };
public static void main(String args[]) {
Example ex = new Example( );
ex.change(ex.str, ex.ch);
System.out.print(ex.str + “and”);
System.out.print(ex.ch);
}
public void change(String str, char ch[]) {
str = “test ok”;
ch[0] = ‘g’;
}
}

A   goodandabc     
B.  goodandgbc     
C.  test okandabc      
D.  test okandgbc    

这里写图片描述

3.以下关于StringBuffer类的代码的执行结果是( )。

public class TestStringBuffer {
public static void main(String args[]) {
StringBuffer a = new StringBuffer(“A”);
StringBuffer b = new StringBuffer(“B”);
mb_operate(a, b);
System.out.println(a + “.” + b);
}
static void mb_operate(StringBuffer x, StringBuffer y) {
x.append(y);
y = x;
}
}

A.  A.B        
B.  A.A        
C.  AB.AB      
D.  AB.B     

这里写图片描述

4.String、StringBuffer性能说明
public class TestStringBuffer3 {
    public static void main(String[] args) {
        //字符串字面常量拼接,编译器进行优化,class文件中已经合并成一个字符串
        String str1 = "hello" +" java";
        String str2 = "hello java";
        System.out.println(str1);
        System.out.println(str2);
        //javap -c TestStringBuffer3 查看虚拟机指令
        //字符串变量的拼接,编译器会使用StringBuilder的append方法进行优化
        //不会生成多个中间字符串
        String str3 = "hello ";
        String str4 = " java";
        String str5 = " coffee";
        String str6 = str3 + str4 + str5;
        /*
        StringBuilder builder = new StringBuilder("");
        builder.append(str3);
        builder.append(str4);
        builder.append(str5);
        String str6 = builder.toString(); 
        */
        System.out.println(str6);

        //使用了循环的字符串变量的拼接
        String str7 = "";
        //采用了append不错,但是每次循环都创建一个新的StringBuilder
        for(int i=0;i<1000;i++){
            str7 = str7 + i;
        }
        System.out.println(str7);

        StringBuilder str8 = new StringBuilder("");
        //循环1000次,一直使用一个StringBuilder,效率高
        for(int i=0;i<1000;i++){
            //str7 = str7 + i;
            str8.append(i);
        }
        System.out.println(str8);
    }
    }
5.编写一段Java程序

把一句英语中的每个单词中的字母次序倒转,单词次序保持不变,
例入输入为“There is a dog.”,输出结果应该是“erehT si a god.”要求不使用Java的库函数,例如String类的split,reverse方法。

函数形如:

    public static String reverseWords(String input) {
        String str = "";

        return str;
    }



思路说明:将字符串转化成字符数组,然后根据数组中空格的位置判断每个单词所占的索引范围,根据得到的索引将数组中的每个单词逆序后拼接到新的字符串中。


public class TestStringReverse{
    public static void main(String[] args) {
        String input = "we should study hard";
        System.out.println("逆转后的字符串为:" + reverseWords(input));
    } 
    public static String reverseWords(String input) {
        StringBuffer buffer = new StringBuffer("");
        //将字符串转化成字符数组
        char[] arr = input.toCharArray();
        //index用来记录每个单词的起始索引
        int index = 0;
        //遍历字符数组,将空格前边的单词挨个拼接到str中
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] == ' '){
                //根据空格位置将空格前边一个单词密续追加到str中
                for(int j = i - 1; j >= index; j--){
                    buffer.append(arr[j]);
                }
                //单词拼接完成后,拼接一个空格
                buffer.append(" ");
                //让index指向下一个单词的起始位置
                index = i + 1;
            }
        }
        //将最后一个单词拼接上
        for(int i = arr.length - 1; i >= index; i--){

            buffer.append(arr[i]);
        }
        return buffer.toString();
    }   
}        

高级知识部分

1.集合

1.集合和数组的相同和不同之处
2.集合框架体系(Collection、List、Set、Map的关系和特点)
3.ArrayList和LinkedList的区别联系;
4.Vector和ArrayList的区别联系;Hashtable和HashMap的区别联系
5.Collection和Collections的区别

2.多线程

1.线程和进程的区别联系
2.多线程三种实现方式
3.线程的生命周期(要说有三种阻塞状态的)
4.简述sleep(),yield()和join()的异同之处
5.多线程同步三种方式
6.简述sleep( )和wait( )异同之处。
7.什么是线程池?为什么使用它?如果提交任务时,线程池队列已满,此时会发生什么?
8.多线程之间如何共享数据
9.ThreadLocal的原理和使用(业务层事务时讲解)

3.设计模式

1.设计模式作用和分类
2.面向对象设计7大原则
3.核心设计模式
1.[简单]工厂模式(SpringBean工厂)
2.单例模式(JDBC、线程池、连接池)
3.装饰模式(IO流、HttpServletRequestWrapper CopyOnWriteArraySet)
4.代理模式(静态代理和动态代理 AOP)
5.命令模式(SpringMVC的DispatcherServlet Struts2的StrutsPrepareAndExecutorFilter)
4.其他设计模式:
职责链模式(Servlet的过滤器、Struts2的拦截器)
模板方法模式(HibernateTemplate)
门面/外观模式(提取业务层)
适配器模式(InputStreamReader)
观察者模式(手机中的各种App的消息推送)
5.请对你所熟悉的一个设计模式进行介绍
分析:建议挑选有一定技术难度,并且在实际开发中应用较多、有生活案例、Java中有实现的设计模式。
可以挑选装饰模式和动态代理模式。

4.数据结构

1.算法的时间复杂度
2.顺序表和链表的特点、优缺点、实现和应用
3.二叉树的遍历思路、结果、代码实现
4.哈希表的原理(HashSet、HashMap的底层结构)
5.二叉查找树的相关算法 (红黑树、TreeMap添加和查询的过程)
递归、查找、排序已经单独列出

5.反射(后续结合应用场景讲解)

1.反射的作用、优缺点
2.Class类的作用?生产Class对象的方法有哪些?
3.反射的语法(创建对象、操作属性、执行方法)
4.反射的应用(Servlet、框架等)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值