JavaSE高级部分包含了哪些

  1. 泛型
  2. 枚举
  3. 多线程 前3年(难)
  4. 集合(数据结构,树,二叉树,红黑树,B+树,B-树)
  5. IO流(文件)
  6. 反射和注解
  7. 网络通信Socket(tomcat、navicat等等)

面试八股文

八股文是什么?其实就是面试中常出现的一些问题,大多都有固定化、格式化的答案,俗称为面经。
八股文就是指文章的八个部分,文体有固定格式:由破题、承题、起讲、入题、起股、中股、后股、束股八部分组成,题目一律出自四书五经中的原文。后四个部分每部分有两股排比对偶的文字,合起来共八股。
包括了:Java基础、Java异常、Java集合、Java并发、Java JVM、SSM框架、MySQL、Redis、计算机网络、操作系统、消息队列与分布式等等

什么是泛型?

广泛的、普通的类型。
泛型能够帮助我们把类型明确的工作,推迟到创建对象或者调方法的时候。
大概意思就是,定义类的时候,不需要考虑这个数组到底要存什么类型。
创建这个超级数组对象的时候把里面要存的数据的类型确定下来。

以前写的超级数组SuperArray只能指定一个类型或者全部类型Object
显得很鸡肋,但是利用泛型就可以解决问题。

public static void main(String[] args) {
    SuperArray superArray = new SuperArray(5);
    superArray.add("你好");
    superArray.add(1);
    superArray.add(1.5);
    // 如果用Object,什么内容都可以存入
}

泛型的修饰

  1. 泛型类
  2. 泛型方法
  3. 泛型接口

泛型类

泛型类把泛型定义在类上,用户在使用类的时候才能把类型给确定。
具体的使用方法使用<>加上一个未知数。通常用T K V E等大写字母表示。
实际上里面的字母什么都可以,类似一个变量。

如果一个泛型类,在创建对象的时候没有指定泛型类型,默认还是Object
在使用这个类的时候,去确定泛型类型,现在这个超级数组就只能存String类型
SuperArray<String> superArray = new SuperArray(); 这个写法并不规范

完整写法,在JDK7以前使用,现在已经不用这么写了
SuperArray<Employee> superArray2 = new SuperArray<Employee>();

现在的写法

JDK7以后,可以省略等号右边的泛型的声明,<>必须得写,规范写法
这个超级数组superArray1就只能存Employee类型
SuperArray<Employee> superArray1 = new SuperArray<>(); 

泛型方法

我们如果只关心某个方法,可以不定义泛型类,只定义泛型方法。
泛型方法不一定要在泛型类里,泛型类里不一定要有泛型方法

在定义泛型方法时,要首先定义泛型类型。
定义在方法中间,泛型的使用处之前。
使用泛型方法,最好要结合返回值,和Object一样。
public class Ch03 {
    
    public <T> T show(T t) {
        // 将t传入,再把t返回
        System.out.println(t);
        return t;
    }
    
    public static void main(String[] args) {
        new Ch03().show("哈哈");
    }
}

泛型类的继承

泛型类在继承时:

  1. 父类是一个泛型类,子类不一定是泛型类。
  2. 泛型的声明只能在当前类名后或者方法中间,而且声明的泛型是自己的。
  3. 在子类继承父类时,子类泛型和父类泛型都写出来的情况下,父跟子。
  4. 如果在继承时,没有写出任何泛型,当前子类就不是泛型类。
class Father<T> {
    T t;
}
// 在确定子类泛型的时刻,父类的泛型和子类一样
class Son<T> extends Father<T> {

}
//
class Son2 extends Father {

}
public class Ch04 {

    public static void main(String[] args) {
        Son<Employee> son = new Son<>();
        son.t = new Employee();
        Son2 son2 = new Son2();
        son2.t.notify();
    }
}

如果在一个泛型类当中,尽量就不要再使用泛型方法,泛型方法多数都是出现在非泛型类。


静态泛型方法

  1. 静态方法如果是泛型方法,泛型的声明必须写。
  2. 因为静态结构是属于类的,不属于某个对象。
interface Inter<T> {
    T show(T t); // 接口参数为T类型

    static <T> T info(T t){
        return t;
    }

}
class Demo01<T> implements Inter<T> {
    @Override
    public T show(T t) { // 重写方法
        return t;
    }
}
public class Ch05 {
    public static void main(String[] args) {
        Inter.info(1);
    }
}

通配符“?”

可以接受任何类型。
如果使用Object类型,别写泛型。
泛型约束类的数据类型。(JDK1.5之后使用泛型)
class Animal {

}

class Dog extends Animal {

}

class Teddy extends Dog {
    public static void show(SuperArray<? super Teddy> superArray) {
        // 含义和传SuperArray类型一致
    }
}

public class Ch06 {

    public static void main(String[] args) {

        SuperArray<Animal> superArray = new SuperArray<>();
        superArray.add(new Animal());
        superArray.add(new Dog());
        superArray.add(new Teddy());
        Teddy.show(superArray);

    }
}

类型参数化

类型擦除:
为了兼容性,使用原始类型(没有泛型)是可以的。
泛型刚刚出现的时候,还存在大量的不适用泛型的代码。
是为了保证代码的兼容性,将参数化类型的实例传递给设计用于原始类型的方法必须是合法的。

为了保持兼容性,Java泛型中,其实有一种类似伪泛型,因为Java在编译期间,所有的泛型都会被擦掉。
Java的泛型语法是在编译期这个维度上实现的。
正常来说在生成的字节码文件中,不包含泛型的类型信息的。
在JVM中看到的只是SuperArray,由泛型附加的类型信息对JVM是看不到的。
可以理解为,泛型的本质就是让程序员在编写代码时遵守的一个规则。
比如SuperArray 在确定了泛型之后,这个超级数组中就统一只放同一类型的数据。如果放入其他类型,编译不通过。

泛型不能是基本数据类型。(原则上来说,数组可以作为泛型,语法角度,不可以)
<>里面放的就应该是类名。数组是在编译后才会生成一个类($xxxx)
方法重载:
a.同一个类里 b.方法名相同 c.参数不同 (原理:类型擦除)

开发中,能够在业务上解决的问题,尽量不要在技术上解决。


泛型的应用场景

  1. 父类(接口)。起到的是一个规范的作用,对里面的数据类型没有明确要求。
  2. 容器类。(超级数组,链表,队列,栈)

当类型无法确定时,使用泛型。
开发中,我们更多的是会使用到一些泛型类或泛型接口。

将超级数组变为泛型

DataContianer接口

public interface DataContainer<T> {

    void add(T t);

    void update(Integer index,T t);

    T remove(Integer index);

    T get(Integer index);

}

SuperArray类

点击展开全部代码

public class SuperArray<T> implements DataContainer<T> {

    // 声明了一个T类型的变量t
    private T t;

    // 维护一个数组,要考虑的是怎么存
    private Object [] array;

    // 超级数组的长度
    private int size;

    // 数组当前的容量
    private int capacity;

    public SuperArray(){
//        array = new Integer[10];
        this(10);
//        capacity = 10;
    }

    public SuperArray(int capacity){
        array = new Object[capacity];
        this.capacity = capacity;
    }

    // 添加数据,默认添加,在数组的尾部添加
    public void add(T data) {
        // 添加时要确保容量足够,如果不够,就需要扩容
        ensureCapacity(size + 1);
        // 真正的添加数据
        array[size++] = data;

    }

    @Override
    public void update(Integer index, T t) {
        set(index,t);
    }


    @Override
    public T get(Integer index) {
        // 判断一下index和合法性
        if(rangeCheck(index)){
            return (T) array[index];
        }
        return null;
    }

    // 添加数据,传入两个参数
    // 在指定位置添加
    public void add(int index,T data){
        if(rangeCheck(index)){
            ensureCapacity(size + 1);
            System.arraycopy(array,index,array,index + 1,size - index);
            // 真正的添加数据
            array[index] = data;
            size++;
        }

    }

    // 删除最后一个数据
    public T remove(){
        if(size > 0){
            return (T) array[--size];
        }
        return null;
    }
    @Override
    // 删除指定下标位置的元素
    public T remove(Integer index){
        if(rangeCheck(index)){
            T res = (T) array[index];
            System.arraycopy(array,index + 1,array,index,(--size - index));
            return res;
        }
        return null;
    }

    // 修改
    private boolean set(int index,T data) {
        if(rangeCheck(index)){
            array[index] = data;
            return true;
        }
        return false;
    }

    // 获取超级数组的长度
    public int size(){

        return size;
    }

    private boolean rangeCheck(int index) {
        // index >= 0
        // index <= size - 1
        return (index >=0 && index <= size - 1);
    }

    // 这个方法只在当前类使用,所以声明成private
    private void ensureCapacity(int needCapacity) {
//        System.out.println(needCapacity + "-----" + capacity);
        if(needCapacity > capacity){
            // 1.5倍
            capacity = capacity + (capacity >> 1);
            //  创建一个新的扩容好的数组
            Object [] newArray = new Object[capacity];
            // 把原数组的数据拷贝过来
            /*
                src:原数组
                srcPos:拷贝原始数组的起始位置
                dest:目标数组
                destPos:目标数组的起始位置
                length:拷贝数据的长度
             */
            System.arraycopy(array,0,newArray,0,array.length);
            array = newArray;
        }


    }

    public static void main(String[] args) {
        SuperArray<String> superArray = new SuperArray<>();
        superArray.add("a");
        superArray.add("d");
        superArray.add("c");
        superArray.add("b");

        for (int i = 0; i < superArray.size(); i++) {
            System.out.println(superArray.get(i));
        }
    }

}


斗地主发牌

public class Cards {

    public static void main(String[] args) {

        ArrayList<String> arrayList = new ArrayList<>();

        for (int i = 0; i < 52; i++) {
            int num = i%13+1;
            String color;
            String numStr = String.valueOf(num);
            if (num == 11) {
                numStr = "J";
            }
            if (num==12) {
                numStr ="Q";
            }
            if (num==13) {
                numStr = "K";
            }
            switch (i/13) {
                case 0:
                    color = "❤";
                    break;
                case 1:
                    color = "\uD83D\uDD39";
                    break;
                case 2:
                    color = "♠";
                    break;
                default:
                    color = "♣";
                    break;
            }
            arrayList.add(numStr+color);
        }
        arrayList.add("大王");
        arrayList.add("小王");
        Collections.shuffle(arrayList);

        ArrayList<String> bigBear = new ArrayList<>();
        ArrayList<String> secBear = new ArrayList<>();
        ArrayList<String> headShot = new ArrayList<>();
        ArrayList<String> lastCards = new ArrayList<>();

        lastCards.add(arrayList.get(0));
        lastCards.add(arrayList.get(1));
        lastCards.add(arrayList.get(2));

        for (int i = 3; i < 54; i++) {
            if (i%3 == 0) {
                bigBear.add(arrayList.get(i));
            } else if (i%3 ==1) {
                secBear.add(arrayList.get(i));
            } else {
                headShot.add(arrayList.get(i));
            }
        }

        System.out.println("熊大"+bigBear);
        System.out.println("熊二"+secBear);
        System.out.println("光头强"+headShot);
        System.out.println("底牌"+lastCards);
    }
}
什么叫做不简单?把简单的事千百遍都做好,就是不简单;
什么叫做不容易?大家都认为非常容易的事情非常认真地去做好它,就是不容易。
—— 张瑞敏
最后修改:2023 年 01 月 09 日
如果觉得我的文章对你有用,请随意赞赏