10.23 每日打卡

类变量和类方法

类变量

有时需要很多个对象对同一个变量进行更改,那么我们就需要一个类变量(静态变量)

  • 使用static修饰的属性

  • 每一个该类实例化的对象都可以共享该变量

  • 可以使用类名+.的方法调用该变量

类变量存放在方法区的静态域里(逻辑上属于堆空间)

类方法

与普通成员方法的区别就是用static修饰

  • 类方法不需要创建对象就可以使用

  • 要求类方法不涉及任何和对象相关的成员

类方法和普通方法都随着类的加载而加载,将结构信息存储在方法区,类方法中无this参数

理解main方法的语法

public static void main(String[] args){}

  1. JVM需要调用类的main方法,所以该对象的访问权限必须是public

  2. JVM在执行main方法时不必创建对象,所以该方法必须是static

  3. 该方法接收String类型的数组参数,该数组保存执行java命令时传递给所运行的类的参数

  4. java执行的程序所需要的参数依次存入args[]

代码块及静态调用的顺序

代码块化也称初始化块,属于类中的方法,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来

  • static{代码};(要么写static,要么什么都不写直接就是{代码};)

  • 普通代码块/静态代码块

  • ;可写可不写

  1. static代码块(静态代码块),随着类的加载而执行且只执行一次;普通代码块,每创建一个对象就执行一次

  2. 类什么时候被加载

    1. 创建对象实例时

    2. 创建子类实例,父类也会被加载

    3. 使用类的静态成员变量时

  3. 普通代码块在实例化时隐式调用(创建一次就调用一次),若只使用类的静态成员时,普通代码块并不会执行

    public class Main {
        public static void main(String[] args) {
                Test.a++;
                Test.a++;
                Test test = new Test();
                Test test0 = new Test();
                Test test1 = new Test();
                Test test2= new Test();
            }
    ​
    }
    class Test{
        static int a = 0;
        static {
            System.out.println("静态代码块");
        }
    ​
        public Test() {
        }
        {
            System.out.println("普通代码块");
        }
    }

  4. 创建对象时,在一个类中调用的顺序为:

    1. 调用静态代码块和静态属性初始化(按顺序来,优先级相同)

    2. 调用普通代码块和普通属性的初始化(同上)

    3. 调用构造方法

package com.wang.Advanced;
​
public class Main {
    public static void main(String[] args) {
            Test.a++;
            Test.a++;
            Test test = new Test();
​
        }
​
}
class Test{
    static int a = 0;
    static {
        System.out.println("静态代码块");
    }
​
​
    {
        System.out.println("普通代码块1");
    }
    {
        System.out.println("普通代码块5");
    }
    public Test() {
        System.out.println("我是构造方法");
​
    }
}
  1. 构造方法的最前面隐含了super()和调用普通代码块

    静态成员的一切在类加载时就执行完毕,因此优先于构造器和普通代码块

  2. 静态代码块只能直接调用静态成员,普通代码块可以调用任意成员

  3. 当有继承关系时,调用顺序如下

    1. 父类的 静态

    2. 子类的 静态

    3. 父类的 普通

    4. 父类的 构造

    5. 子类的 普通

    6. 子类的 构造

单例设计模式

设计模式:目的是实现代码的高内聚和低耦合(23种)

  • 解决软件开发某些特定问题而提出的一些解决方案

  • 遵循六大原则

    • 开闭原则

    • 里氏代换原则

    • 单一职责原则

    • 接口隔离原则

    • 依赖倒转原则

    • 最少知道原则(迪米特法则)

单例设计模式:采取一定的方法保证整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

  1. 饿汉式

  2. 懒汉式

单例设计模式的步骤(饿汉式):主程序中还不需要该对象时,类中就已经通过静态类方法创建好等着了

  1. 构造器私有化(防止用户直接new创建对象)

  2. 类的内部创建对象(需要将其修饰为static)

  3. 向外暴露一个静态的公共方法(getInstance)

  4. 代码实现

package com.wang.Advanced;
​
public class SingletonModeTest {
    public static void main(String[] args) {
        Mother mother = Mother.getInstance();
        Mother mother1 = Mother.getInstance();
        System.out.println(mother.getName());
        System.out.println(mother1.getName());
    }
​
}
//有一个类,Mother
//只能有一个mama
​
class Mother{
    private String name;
    private Mother(String name){
        this.name = name;
    }
    private static Mother mother = new Mother("maa");
​
    public static Mother getInstance(){
        return mother;
​
}
​
    public String getName() {
        return name;
    }
}

单例设计模式的步骤(懒汉式):使用的时候才创建(饿汉式可能造成内存浪费)

public class SingletonModeTest {
    public static void main(String[] args) {
        Mother mother = Mother.getInstance();
        Mother mother1 = Mother.getInstance();
        System.out.println(mother.getName());
        System.out.println(mother1.getName());
    }
​
}
//有一个类,Mother
//只能有一个mama
​
class Mother{
    private String name;
    private Mother(String name){
        this.name = name;
    }
    public static Mother mother;
    //在没有调用getInstance方法之前,只是声明了mother对象,并没有创建
    //如果调用时发现还未创建就创建,已创建就直接返回
    public static Mother getInstance(){
        if(mother==null)
            mother = new Mother("mama");
        return mother;
​
}
​
    public String getName() {
        return name;
    }
}

final

用于修饰类,属性,方法和局部变量

  • 不希望类被继承

  • 不希望父类的某些方法被子类重写

  • 不希望类的某个属性(变量)被修改

  1. final修饰的属性也叫常量用下划线区分单词

  2. final修饰的属性可以在以下情况赋值(但不能修改)

    1. 定义时

    2. 构造器中

    3. 代码块中

  3. 如果final的属性是static,以上三种方法中构造器就不能使用了

  4. final类不能被继承但是可以实例化

  5. 如果类不是final类,但是含有final的方法,该方法不能继承,但是可以重写

  6. final和static往往搭配使用,效率更高,底层编译器做了优化处理

  7. 包装类(Intger...)和String类都是final类

抽象类

当父类的某些方法需要声明但不知道如何实现时,可以将其声明为抽象方法,这个类就是抽象类

  • 当一个类中存在抽象方法时,该类也必须声明为abstract

  • 抽象类的价值就在于设计,由子类实现

abstract class  Animal{
private String name;
public Animal(String name){
        this.name=name;
        }
//抽象方法没有方法体
public abstract void eat();
    
        }
​
  1. 抽象类不能被实例化

  2. 抽象类可以没有抽象方法

  3. abstract只能修饰类和方法,不能修饰属性和其他的

  4. 如果一个类继承了抽象类,则他必须实现抽象类的所有抽象方法,除非他也为自己声明为抽象类

接口

接口给出一些没有实现的方法,封装到一起

  • 接口不能实例化

  • 接口中所有方法都是public方法

  • 接口中的抽象方法,可以不用abstract修饰

  • 一个类要实现接口,就必须将该接口的所有方法都实现

  • 抽象类实现接口,可以不用实现接口方法

  • 一个类同时可以实现多个接口

  • 接口中的属性只能是public final static修饰符

  • 一个接口只能继承别的接口

  • 接口的修饰符只能是public和默认

接口的多态

  1. 多态参数,若某方法形参为接口,传递的实参可以是实现了接口功能的各种对象

  2. 多态数组,类似继承的多态

  3. 多态传递

public class Test {
    public static void main(String[] args) {
        IG ig = new Teacher();
        //多态传递
        IH ih = new Teacher();
    }
​
}
​
interface IH{
​
}
//多态传递
interface IG extends IH{}
class Teacher implements IG{}

继承VS接口

  1. 继承在于代码复用和维护

  2. 接口在于设计

  3. 接口比继承更灵活

  4. 接口一定程度上实现了代码解耦

内部类

一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类

  • 内部类可以直接访问私有属性,并且可以体现类与类之间的包含关系

  1. 定义在外部类局部位置上的(比如方法内)

    1. 局部内部类(有类名)

    2. 匿名内部类(没有类名)

  2. 定义在外部类成员位置上

    1. 成员内部类(没用static修饰)

    2. 静态内部类(使用static修饰)

局部内部类

是定义在外部类的局部位置的

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,但是可以用final修饰

  3. 作用域:仅仅在定义他的方法和代码块中

  4. 局部内部类访问外部类的成员是直接访问

  5. 外部类的成员访问局部内部类需要先实例化内部类的对象,再去访问(必须在作用域内)

  6. 外部其它类不能访问局部内部类,局部内部类实际上是一个局部变量

  7. 如果外部类和局部内部类成员重名时,默认遵循就近原则,也可以外部类名.this.成员去访问

package com.wang.Advanced;
​
import java.security.DigestException;
​
//外部其它类
public class TestInnerclass {
​
​
}
//外部类
class Outer{
    private int a = 100;
​
    public Outer(int a) {
        this.a = a;
    }
​
    public void m1(){
        System.out.println("我是方法");
        //局部内部类Inner_,在m1方法下
        //除了final修饰符,别的修饰符都不能用
        //Inner_类只能在方法m1中使用
        final class Inner_{
            public void f1(){
                //局部内部类可以直接访问外部类的属性包括私有成员
                System.out.println(a+"我是局部内部类");
            }
​
            public Inner_() {
            }
        }
​
    //外部类在方法m1中可以创建局部内部类Dog的对象,然后调用方法
    Inner_ inner_ = new Inner_();
        inner_.f1();
}
​
    {
        System.out.println("我是代码块");
    }
​
}

匿名内部类 (重要!!!!)

  1. 本质是类

  2. 是内部类

  3. 该类没有名字

  4. 同时还是一个对象

基于接口的匿名内部类:

package com.wang.Advanced;
​
import java.security.DigestException;
​
//外部其它类
public class TestInnerclass {
    public static void main(String[] args) {
        new Outer(50).m1();
    }
​
​
}
//外部类
class Outer{
    private int a = 100;
​
    public Outer(int a) {
        this.a = a;
    }
​
    public void m1() {
        //基于接口的匿名内部类
        //1.需要使用接口A,并创建对象
        //传统方法:写一个类,实现该接口,并创建对象
        //2.匿名内部类的方法
        //a的编译类型是接口
        //a的运行类型是匿名内部类
        /*/
           底层实现的匿名内部类XXXX:
           class XXXX implements A{
           @Override
            public void AA() {
                System.out.println("AAAAA");
            }
           }
           XXXX => Outer$1
         */
        //3.jdk底层匿名内部类创建完成后,立即创建了XXXX的实例,并且返回地址给a
        //4.匿名内部类使用一次就不能再使用了,但是实例对象已经创建好了,可以反复调用
        A a = new A(){
            @Override
            public void AA() {
                System.out.println("AAAAA");
            }
        };
        System.out.println(a.getClass());
        //此时匿名内部类已经消失了,但是还维持着对象和调用它的地址
        a.AA();
        a.AA();
        a.AA();
    }
​
​
}
interface A{
    public void AA();
}

基于类的匿名内部类:

如果是抽象类,那么必须重写抽象方法

       //基于类的匿名内部类
        //编译类型是B
        //运行类型是Outer$2
        /*
        class Outer$2 extends B{

        }
        返回了Outer$2的对象
         */
        B b = new B(){

        };
    }
class B{

}

使用场景

当做实参直接传递

package com.wang.Advanced;

import java.security.DigestException;

//外部其它类
public class TestInnerclass {
    public static void main(String[] args) {
        //此处传递的实参就是匿名内部类的实现对象
        f1(new A() {
            @Override
            public void AA() {
                System.out.println("这是接口实现的方法");
            }
        });
    }

    //静态方法,形参是接口类型
    public static void f1(A a) {
        a.AA();
    }
}
interface A{
    public void AA();
}

成员内部类

成员内部类定义在外部类的成员位置,并且没有static修饰

  • 作用域:和其他成员一样

  • 和属性一样,可以访问外部类,外部类和外部其它类都可以直接访问,不需要实例化对象

public class TestInnerclass {
    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.m1();

    }

}

class Outer{
    private int a= 10;
    //成员内部类,与局部内部类不同的是,成员内部类不用写在方法下
    class Inner01{
        public void say(){
            //可以直接访问所有成员,包括私有的
            System.out.println(a+"a");
        }
    }
    public void m1(){
        //使用成员内部类
        
        Inner01 inner01 = new Inner01();
        inner01.say();
    }

}

静态内部类

在成员内部类前加static

  • 只能访问外部类的静态成员(直接访问)

  • 可以添加任意修饰符

  • 作用域(同成员内部类)

  • 外部类访问必须创建对象再访问(与普通成员内部类不同)

  • 外部其它类可以直接访问静态内部类

package com.wang.Advanced;

import java.security.DigestException;

//外部其它类
public class TestInnerclass {
    public static void main(String[] args) {

        Outer outer = new Outer();
        outer.m1();
        //外部其它类访问静态内部类,外部类名.静态内部类名
        Outer.Inner01 inner01 = new Outer.Inner01();
        inner01.s();

    }

}

class Outer{
    private int a= 10;
    private static final int b = 10;
    //静态内部类,放在外部类的成员位置,被static修饰
    //可以直接访问外部类的所有静态成员,但不能访问非静态成员,访问a就会出错
    public static class Inner01{
        public void s(){
            System.out.println(b);
        }
    }
    //外部类访问必须创建对象再访问(与普通成员内部类不同)
    public void m1(){
        Inner01 inner01 = new Inner01();
        inner01.s();
    }



}

异常

正常情况下,抛出异常后程序就崩溃退出了,之后的代码就不再执行

所以需要异常处理机制

如果程序猿认为一段代码可能出现问题,可以使用try-catch异常处理机制处理

  1. 选中该代码块->ctrl + alt + t->try-catch

  2. 捕获异常后,会继续进行程序

异常分为

  • Error :JVM无法解决的严重问题

  • Exception:其他因编程错误或偶然的外在因素导致的一般问题

    • 运行时异常

    • 编译时异常

异常体系图

常见的运行时的异常

  1. NullPointerException空指针异常

  2. ArithmeticException数学运算异常

  3. ArrayIndexOutOfBoundsException数组下标越界异常

  4. ClassCastException类型转换异常

  5. NumberFormatException数字格式不正确异常

编译异常

一般发生在网络,数据库,文件操作编程中

异常处理的机制

  1. try-catch-finally 程序员在代码中捕获发生的异常,自行处理

  2. throws 将发生的异常抛出,交给调用者(方法)来处理,最顶级的处理者就是JVM

  3. 通常将释放资源的代码放在finally上

  1. JVM处理异常的机制就是直接输出错误信息然后退出

try-catch

try中的语句一旦发生异常,接下来的程序就不在运行,而是直接进入catch块

枚举

  1. 枚举是一组常量的集合

  2. 枚举属于一种特殊的类,里面只包含一组有限的特定的对象

枚举的实现方式:

  1. 自定义类实现枚举

    1. 枚举对象通常为只读(不需要set方法)

    2. 对枚举对象/属性使用final+static共同修饰,实现底层优化

    3. 枚举对象通常使用全部大写

    4. 枚举对象根据需要也可以有多个属性

package com.wang.Advanced.Enum;
​
public class TestEnum {
    public static void main(String[] args) {
        System.out.println(Season.AUTUMN.getDesc());
​
    }
​
}
class Season{
    private String name;
    private String desc;
    //直接在类内创建固定的对象
    public final static Season SPRING = new Season("春天","c");
    public final static Season WINTER = new Season("冬天","d");
    public final static Season AUTUMN = new Season("秋天","q");
    public final static Season SUMMER = new Season("夏天","x");
​
​
    //构造方法设置为private,防止直接new
    //去掉set方法,防止属性被修改
​
    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
​
    public String getName() {
        return name;
    }
​
    public String getDesc() {
        return desc;
    }
​
}
  1. enum关键字实现枚举

package com.wang.Advanced.Enum;
​
public class TestEnum0 {
    public static void main(String[] args) {
        System.out.println(Season2.SPRING.getDesc());
​
    }
​
}
//使用enum关键字来实现枚举类
enum Season2{
    //1.使用关键字enum替代class
    //2.public final static Season2 SPRING = new Season2("春天","c");
    //变为SPRING("春天","c");   常量名(实参列表)
    //3.如果有多个常量,使用逗号间隔即可
    //4.使用枚举时,必须将定义常量写在最前面
    SPRING("春天","c"),WINTER("冬天","d");
    private String name;
    private String desc;
​
    private Season2(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
​
    public String getName() {
        return name;
    }
​
    public String getDesc() {
        return desc;
    }
​
}

  • 使用enum关键字开发枚举类时,默认会继承Enum类,而且是final类

  • 多个枚举对象用逗号间隔

Enum类的各种方法的使用

注解

基本注解

  1. @Override重写

  2. @Deprecated表示某个类或方法已过时

  3. @SupressWarnings抑制编译器警告

元注解

  • @Target是修饰注解的注解,称为元注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值