Java基础知识

前言

1. 接口

Java前面的很多基础知识,我都没有整理成博客,如果需要的话,可以去看我的Gitee,https://gitee.com/once-three-hearted-grass/java

1.1 认识接口

实现接口要用关键字interface

public interface A {
}

这就是一个接口,接口里面只能写成员变量和方法,而且成员变量就是常量
在这里插入图片描述
看这个可以看出public static final是灰色的,说明不写也是默认的public static final

public interface A {
    int a=0;
}
System.out.println(A.a);

在这里插入图片描述
接口里面的方法也是抽象方法
在这里插入图片描述
所以接口不能定义出对象

在这里插入图片描述
而且接口里面只能有成员变量和方法,不能有代码块,构造方法

接口是用来被类来实现的,一个类可以继承多个接口,然后类还必须实现完接口的全部抽象方法

public interface C {
}
public class B implements A,C {
    @Override
    public void test() {

    }
}

1.2 接口新增三种方法

默认方法,这个方法必须要用default修饰,而且默认是public的,接口因为要被继承,所以方法都是默认public的

public interface A {
    int a=0;
    public abstract void test();
    default void test1(){
        System.out.println("aaaaa");
    }
}

这个test1的方法就相当于是一个普通方法,能够被对象调用使用
由于接口无法创建对象,所以只能由继承它的子类去调用

B b=new B();
b.test1();

在这里插入图片描述
第二个就是私有方法,这个方法必须使用private修饰,不然的话,就会默认使用public修饰,就是普通的抽象方法了

 default void test1(){
        System.out.println("aaaaa");
        test2();
    }

    private void test2(){
        System.out.println("bbbbb");
    }

由于这个是私有的,也不能被子类继承,所以就只能在自己类里面使用
只能在默认方法里面使用,才能发挥价值了
在这里插入图片描述
第三个就是静态方法
用static修饰的方法

 static void test3(){
        System.out.println("ccccc");
    }
 A.test3();

在这里插入图片描述
既然是静态方法,那么就可以用类名进行访问了

1.3 多继承

类继承接口用的implements
接口继承接口用的就是extends

public interface D extends A,C{
}

而且是可以多继承的,这样的好处就是,多个接口合在一起了,这样用子类继承的时候,就只用写D这一个了
注意事项

public interface A {
    int a=0;
    public abstract void test();
    default void test1(){
        System.out.println("aaaaa");
        test2();
    }

    private void test2(){
        System.out.println("bbbbb");
    }

    static void test3() {
        System.out.println("ccccc");
    }
}
public interface C {
    int test();
}

接口继承多个接口时,如果返回值不一样,不能被多继承,因为不知道怎么实现了,也不能被多实现,,参数不一样的话,还可以继承

一个类继承了父类,也继承了接口,父类和接口有同名的默认方法,那么会优先使用父类的默认方法

一个类实现了多个接口,如果多个接口有同名的默认方法,会冲突

public interface C {
    default void test1(){
        System.out.println("aaaaa");
    }
}

在这里插入图片描述
但如果想不冲突的话,可以去类里面重写这个方法

**public class B implements D {
    @Override
    public void test() {

    }

    public void test1() {

    }
    public void test(int a) {

    }
}**

类里面重写了这个test1方法,那么下次调用就会调用这个方法

2. 内部类

如果一个类定义在另一个类的里面,那么这里面的这个类就是内部类

2.1 成员内部类

public class Outer {
    public class Inner{
        int a;
        public void test1(){
            System.out.println("aaaaaaaa");
        }
    }
}

public class这个就是成员内部类,和普通的类一样,成员内部类里面想定义什么就定义什么

Outer.Inner in=new Outer().new Inner();

创建外部类就不用说了,创建内部类就是这样的,要先new出外部类,然后才可以new出内部类

public class Outer {
    int a=10;
    public class Inner{
        int a=20;
        public void test1(){
            int a=30;
            System.out.println("aaaaaaaa");
        }
    }
}

看这个,如何打印出三个a的值呢

public class Outer {
    int a=10;
    public class Inner{
        int a=20;
        public void test1(){
            int a=30;
            System.out.println("aaaaaaaa");
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(Outer.this.a);
        }
    }
}

在这里插入图片描述

这样就可以了,当然还是就近原则,如果局部没有a,就不用this了
就这样我们就可以访问局部a,内部类的a,和外部类的a了

2.2 静态内部类

public class Outer {
    int a=10;
    public static class Inner{
        int a=20;
        public void test1(){
            
        }
    }
}

虽然静态内部类是里面的类,但是使用起来,就是相当于一个独立出来的类
所以创建对象的时候就不用先创建外部类,在创建内部类了

Outer.Inner in=new Outer.Inner();

创建内部类的对象的时候就这样就可以了

在这里插入图片描述
然后就是内部类只能访问外部类的静态成员,非静态成员是无法访问的,

2.3 局部内部类

这个内部类就是定义在外部类的成员方法里面的类,出了作用域就被销毁了,没什么用

2.4 匿名内部类

匿名内部类就是相当于匿名对象那样,这个你不用创建类,直接就创建好了对象

abstract class Outer {
    int a=10;
    static int b=20;
    abstract void test();
}
new Outer(){
            @Override
            void test(){

            }
        };

这就是一个匿名内部类,这个代码的作用就相当于就是,先用个子类继承,重写抽象方法,然后在new出来,所以可以用一个父类去接收

public class test {
    public static void main(String[] args) {
        Outer in=new Outer(){
            @Override
            void test(){
                System.out.println("aaaaa");
            }
        };
        in.test();
    }
}

这样写就不用再创建一个子类去接收了
在这里插入图片描述

2.5 实例

接下来我们讲的这个实例是一个GUL编程,不太懂也没事

public class test {
    public static void main(String[] args) {
        JFrame win=new JFrame("登录界面");//创建一个登录界面
        JButton btn=new JButton("登录");//创建一个登录按钮
        win.add(btn);
        win.setSize(400,400);//设置窗口大小
        win.setLocationRelativeTo(null);//窗口居中
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//设置一个关闭按钮
        win.setVisible(true);//可以看见窗口
    }
}

在这里插入图片描述
但是点了登录也没有反应,而且还可以点除了登录以外的其他部分,所以我们还要修改一下
要给登录按钮一个事件

public class test {
    public static void main(String[] args) {
        JFrame win=new JFrame("登录界面");//创建一个登录界面
        JPanel panel=new JPanel();//创建一个面板,防止点到了其他部分,有了面板,那么就点不到其他部分了
        win.add(panel);//覆盖面板上去
        JButton btn=new JButton("登录");//创建一个登录按钮
        panel.add(btn);//面板上面增加按钮
        //btn.addActionListener();//括号里面增加的就是事件
        win.setSize(400,400);//设置窗口大小
        win.setLocationRelativeTo(null);//窗口居中
win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//设置一个关闭按钮
        win.setVisible(true);//可以看见窗口
    }
}

如何给按键增加事件呢,我们可以查看这个方法的定义,左手ctrl,右手点击就可以查看方法定义了
在这里插入图片描述
然后ActionListener是一个接口
在这里插入图片描述
所以我们可以创建一个这个接口的子类对象,反正父类可以接受子类的
创建这个接口的子类对象那么就用匿名对象了

btn.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //
            }
        });

然后actionPerformed就是要表演的事件了

public class test {
    public static void main(String[] args) {
        JFrame win=new JFrame("登录界面");//创建一个登录界面
        JPanel panel=new JPanel();//创建一个面板,防止点到了其他部分,有了面板,那么就点不到其他部分了
        win.add(panel);//覆盖面板上去

        JButton btn=new JButton("登录");//创建一个登录按钮
        panel.add(btn);//面板上面增加按钮

        btn.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win,"登录一下");//这个就是在桌面上打印登录一下
            }
        });
        win.setSize(400,400);//设置窗口大小
        win.setLocationRelativeTo(null);//窗口居中
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//设置一个关闭按钮
        win.setVisible(true);//可以看见窗口
    }
}

在这里插入图片描述
或者后面我们可以使用lamda表达式,这个创建对象比匿名还简单

3. 枚举

3.1 基本概念

public enum A {
    X,Y,Z;
}

枚举的第一行只能写一些变量名,变量与变量之间用逗号隔开,这些都是枚举类型的变量,而且都是常量
然后后面的内容就和普通的类是一样的了

public enum A {
    X,Y,Z;
    
    int a=10;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }
}

但是如何创建变量呢

A a1=A.X;
System.out.println(a1);

在这里插入图片描述
创建变量就这样创建变量,直接用.操作符就可以了
然后因为说了的,枚举的类型都是常量,所以打印出来的也都是常量,就直接打印出变量名了

因为枚举类型只有那么几个变量,所以它的构造器是私有的,是在第一行的时候就调用的
在这里插入图片描述
在这里插入图片描述
第一枚举类不能创建对象
在这里插入图片描述

第二就是枚举类都是最终类,不能被继承,是用final修饰的
第三就是枚举类提供了一些额外的API,就是方法

A[] arr=A.values();//这个values会拿到A的全部对象,然后返回在一个数组中
        A a3=A.valueOf("Z");//这个就是指定拿到常量Z
        System.out.println(a3.name());//这个就是返回a3的名字,就是Z
        System.out.println(a3.ordinal());//这个就是返回a3变量的下标,,X下表为0,和数组一样

在这里插入图片描述

3.2 抽象枚举

接下来我们来讲一下抽象枚举,何谓抽象枚举呢,这个的意思就是,枚举中有抽象方法,然后每个变量都要重载这个抽象方法的意思

public enum A {
    X(){
        @Override
        public void go() {
            
        }
    },Y(10){
        @Override
        public void go() {
            ;
        }
    };
    int a=10;

    public abstract void go();
    
    A(int a) {
        this.a = a;
    }

    A(){}

}

我们看这个就可以了,在第一排重写方法的时候,()里面的内容就对应了构造方法,然后就是一定要重写抽象方法,不然根本无法使用对应的抽象方法

在讲一下枚举作用下的单例模式

public enum B {
    X;
}

就这样就可以l了

3.3 应用

枚举一个比较重要的作用就是它的对象也就是常量,可以作为swich语句

public enum B {
    X,Y,Z;
}
B b=B.X;
        switch (b){
            case X:
                System.out.println("这个是X");
                break;
            case Y:
                System.out.println("这个是Y");
                break;
            case Z:
                System.out.println("这个是Z");
                break;
        }

在这里插入图片描述

4. 泛型

这里的泛型是和<>结合的,与C++的模板实例化很相似

4.1 认识一下

在这里插入图片描述
看这个普通的ArrayList是可以接受Object类型的,就是可以接收任意类型的
在这里插入图片描述
看这个指定了String,那么就只能填入String了

ArrayList<String> arr=new ArrayList<>();
        arr.add("aa");

然后就是后面的那个String可以省略掉
像这样<>里面可以放类型的就是泛型

4.2 简单模拟StringList

在这里插入图片描述
还不能这样写,因为Java中是不能创建泛型类型的数组的,只能写Object了,为什么写这个呢,因为我们传入的E(只能引用类型),肯定 直接或间接继承了Object的,第一可以创建数组,对象,第二就算创建了也不影响,因为子类可以赋值给父类,这也是E只能为引用类型的原因,因为普通类型无法继承

public class MyStringList<E> {
    private Object[] arr=new Object[10];
    private int size;

    public boolean add(E e){
        arr[size]=e;
        return true;
    }
}

在这里插入图片描述
如果没有指明E的类型,那么就默认是Object的了,就可以插入任意类型了

MyStringList<String> ar=new MyStringList<>();
        ar.add("aaaa");

在这里插入图片描述
这个函数这样写还不行,因为类型不匹配

public E get(int index){
        return (E)arr[index];
    }

这样写就可以了

4.3 增加知识

除了有一个泛型变量外,还可以有多个

public class MyClass<E,T> {
    
}
MyClass<String,String> m=new MyClass<>();

这里就需要写两个泛型了,要么就一个都不写

public class MyClass<E extends A> {

}
public class B extends A{

}

这里就表示传入的泛型必须是A的子类或者就是A本身

MyClass<A> m=new MyClass<>();
        MyClass<B> m1=new MyClass<>();

4.4 泛型接口

这里的泛型接口的意思就是接口也设置了泛型

public interface Data<E> {
    public boolean add(E e);
    public E get(int index);
}

这就是一个泛型接口,因为接口无法创建出对象,所以接口就无法实例化,但是接口必须被继承,所以就要在继承那里实例化了

public class AData implements Data<A>{
    @Override
    public A get(int index) {
        return null;
    }

    @Override
    public boolean add(A a) {
        return false;
    }
}

看这个,AData继承了Data,那么顺便就把泛型传过去了

4.5 泛型方法

泛型方法就是在方法那里加上泛型,具体表现为

public static <T> void print(T t){
        System.out.println(t);
    }

这个就是泛型方法,<>放在返回值的前面

print("aaaaa");
        print(1);

它的使用就是这样使用的,不用特地说明T是什么类型,直接在传参的时候就确定了T是什么类型,,<>里面不能放普通类型,但是传参的时候就可以放普通类型,为什么呢,待会说一下

public boolean add(E e);

上面这个就不是泛型方法,因为泛型方法是在传参的时候才确定泛型,而这个是在创建类变量的时候就确定了,这个E就是相当于一个类型了,不是泛型

public static <T> void go(ArrayList<T> a){

    }
ArrayList<String> arr=new ArrayList<>();
        arr.add("aa");
        arr.add("bb");
        arr.add("cc");
        go(arr);

这里写ArrayList的目的就是指明只能传ArrayList才能确定这个泛型,不然随便传个引用类型变量就确定了

public static <T extends A> void go(ArrayList<T> a){

    }

这个就表示ArrayList里面的T必须还是A的子类,或者A本身

ArrayList<B> arr=new ArrayList<>();
        B b1=new B();
        B b2=new B();
        arr.add(b1);
        arr.add(b2);
        go(arr);

这个

public static <T> void go(ArrayList<T> a){

    }

就等价于

public static void go(ArrayList<?> a){

    }

这个问号就表示接受的是ArrayList<?>类型的,里面的?表示任意类型

这个

public static <T extends A> void go(ArrayList<T> a){

    }

也等价于

 public static void go(ArrayList<? extends A> a){

    }

表示任意类型,这个类型还是A的子类或者A

这个?就叫做通配符,,,,extends A叫做它的上限,表示最上可以是A,要么就是A的子类

如果是super A的话,这个就表示是它的下限,表示,最差是A,要么就是A的父类

在这里插入图片描述
泛型不支持基本数据类型,因为int并没有继承Object,所以是不行的,,但是如果我们就是要传入int数据呢,可以这样

ArrayList<Integer> qq=new ArrayList<>();
        qq.add(1);
        qq.add(1);
        qq.add(1);

Integer和int是一个意思,只不过它是一个类,继承了Object,所以可以被使用

ArrayList<Double> qq=new ArrayList<>();
        qq.add(1.1);
        qq.add(1.3);
        qq.add(1.3);

至于double就用Double

这也是为什么泛型方法时可以传入int数据了,因为被当做了Integer,所以就可以用了

总结

这一节讲的主要是Java的一些基本知识,下一次讲的就应该是Java的主要API了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值