Java——面向对象(关键字及其他类结构)

一、static关键字及单例设计模式(static的应用)

1.static关键字

1.1 static作用

让一个成员变量(属性、方法)被类的所有实例共享;这种被static修饰类变量、类方法也称为静态变量、静态方法

静态变量和实例变量:
①个数:静态变量在内存空间中只有一份,被类的多个对象共享;实例变量在类的每一个实例(或对象)中都保存了一份
②内存位置:静态变量在jdk6及之前存放在方法区,在jdk7及之后存放在堆空间;实例变量存放在堆空间对象实体中
③加载时机:静态变量随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份;实例变量随着对象创建而加载,每个对象都有一份实例变量
④调用者:静态变量可以被类直接调用,也可以使用对象调用;实例变量只能使用对象调用
⑤生命周期(判断是否可调用):静态变量随着类的卸载而消亡;实例变量随着对象的消亡而消亡

1.2 static修饰方法:

  • ①随着类加载而加载
  • ②可以通过“类.静态方法”直接调用
  • ③静态方法内可以调用静态的属性或方法(当前类的静态属性或方法,类前缀可省略),不可以调用非静态的结构
  • ④static修饰的方法内,不能用super和this
  • ⑤在类的非静态方法中,可以调用当前类的静态结构(属性、方法)或非静态结构(属性、方法)

1.3 static的应用:

  • ①判断当前类的多个实例是否共享此成员变量,且成员变量是相同的
  • ②常量可以声明为静态的(如Math类中的PI)
  • ③方法内操作的变量都是静态变量(非实例变量),则此方法建议声明为静态方法
  • ④工具类中的方法常声明为静态方法(如Arrays类、Math类)–>举例见tool包中Swap类
class Customer{
    //属性
    private int id;
    private static String address;
    private String name;
    private static int inst = 1001;

    //构造器
    public Customer(){
        id = inst;
        inst++;
    }
    public Customer(String name){
        id = inst;
        address = "南京";
        this.name = name;

        inst++;
    }

    //方法
    public static void setAddress(String cAddress) {
        address = cAddress;
    }
    public static String getAddress(){
        return address;
    }
    
    public void show(){
        System.out.println("客户注册数:" + (inst-1001) + ",客户ID:" +id + ",注册地址:" + address + ",客户名:" + name);
    }
}

public class StaticExer {
    public static void main(String[] args) {
        Customer.setAddress("北京");//类.方法
        Customer customer1 = new Customer();
        customer1.show();
        Customer customer2 = new Customer("ZSH");
        customer2.show();
        Customer customer3 = new Customer();
        customer3.show();
        Customer customer4 = new Customer();
        Customer.setAddress("上海");//static只要改一次后面都会以改动值为准
        customer4.show();
    }
}

2.单例模式

设计模式:在大量实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式

2.1 单例概念

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

2.2 单例实现

要让类在一个虚拟机中只产生一个对象,需先将类构造器的访问权限设置为private,这样就不能用new操作符在类外产生类的对象,但在类的内部还是可以产生该类的对象;因为在类的外部无法得到类的对象,只能调用该类的静态方法返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以指向类内部产生的该类对象的变量也必须定义成静态的

  • 饿汉式:“立即加载”,随着类的创建,当前唯一实例就创建–>相对写法简单,内存较早加载实例,使用更方便,线程安全;但是创建实例会花费时间,且会占用内存
  • 懒汉式:“延迟加载”,在需要使用时进行创建–>在需要时创建,节省内存空间;但是线程不安全
//饿汉式
class Bank{
    //构造器私有化
    private Bank(){
    }

    //实例化,为了后续静态方法能使用,此(属性)实例必须也静态化
    private static Bank bankInstance = new Bank();//Instance:实例

    //使用get()获取当前实例,get()必须静态化
    public static Bank getBankInstance(){
        return bankInstance;
    }
}

//懒汉式
class ID{
    //构造器私有化
    private ID(){
    }

    //声明当前实例
    private static ID idInstance = null;

    //通过getXxx()获取当前实例,若未创建实例则进行创建
    public static ID getIDInstance(){
        if(idInstance == null){
            idInstance = new ID();
        }
        return idInstance;
    }
}


public class SingletonExer {
    public static void main(String[] args) {
        Bank bank1 = Bank.getBankInstance();
        Bank bank2 = Bank.getBankInstance();
        System.out.println(bank1 == bank2);

        ID id1 = ID.getIDInstance();
        ID id2 = ID.getIDInstance();
        System.out.println(id1 == id2);
    }
}

3.main()的理解

理解:一个普通静态方法;作为程序入口,不可轻易更改

public class MainExer {
    public static void main(String[] args) {//作为程序入口
        Main.main(new String[4]);

        Main.main(new String[]{"AA","BB","CC","DD"});
    }
}

class Main{
    public static void main(String[] args) {//看作是普通静态方法
        System.out.println("Main中main的调用");
        for (int i = 0; i < args.length; i++) {
            System.out.print(args[i] + "\t");
        }
        System.out.println();
    }
}

二、代码块(初始化块)使用

代码块初始化优先级和显示赋值(初始化)优先级一致,高于构造器赋值(初始化)

1.作用

静态代码块用于初始化的信息非静态代码块用于初始化对象的信息;内部均可以声明变量、调用属性或方法、编写输出语句

2.修饰及分类

只能使用static进行修饰;分类如下

静态代码块:
static{
	//代码……
}
非静态代码块:
{
	//代码……
}

3.执行

静态代码块随着类的加载而执行(类加载只执行一次,所以静态代码块也只执行1次);非静态代码块随着对象创建而执行(每创建当前类的一个实例,就会执行一次非静态代码块)

特点:

  • 1.静态代码块执行优先于非静态代码块;声明多个静态代码块则按照声明先后顺序执行;静态代码块内只能调用静态结构,不能调用非静态结构
  • 2.若声明多个非静态代码块,则按照声明先后顺序执行;非静态代码块可以调用静态结构,也可以调用非静态结构
/**
 * 此处代码分析如下:
 * 首先加载最顶级类Object;然后加载Root类,然后加载Mid类,然后加载Load的类
 * static关键字修饰成员随着类加载而加载
 * 类加载完毕后开始类成员(普通代码块、属性、方法、构造器)加载
 * 在创建new Load()时会调用Load类的构造器,构造器内会先调用super("Load")即Mid的带参构造器Mid(String str)
 * Mid的带参构造器又会先调用this()即Mid的无参构造器Mid()
 * Mid的无参构造器又会先调用super()即Root的无参构造器Root()
 * Root的无参构造器又会先调用super()即Object的无参构造器Object()
 * Object()中无内容,所以会先执行Root中的语句
 * 因为代码块初始化优先级和显示赋值(初始化)优先级一致,高于构造器赋值(初始化),所以会先执行普通代码块内容(静态代码块已执行),再执行空参构造器内容
 * 执行完毕后向下执行Root子类Mid的语句,先执行代码块,再执行空参构造器,再执行带参构造器(带参构造器调用的空参构造器)
 * 执行完毕后再向下执行Mid子类Load的语句,先执行代码块,再执行构造器
 * 最后调用完毕,对象创建完成
 * 注意:Root中静态方法虽然在类加载时也被加载了,但因为没被调用所以不会被执行
 *
 * 父类先于子类执行;静态先于非静态
 */

class Root{
    static{
        System.out.println("Root的静态初始化块--类加载");
    }
    {
        System.out.println("Root的普通初始化快--对象加载");
    }

    public Root(){
        super();//可省略,默认会创建,向上继承父类Object的空参构造器
        System.out.println("Root的无参构造器");
    }
    public static void show(){
        System.out.println("hello !");
    }
}

class Mid extends Root{
    static{
        System.out.println("Mid的静态初始化块--类加载");
    }
    {
        System.out.println("Mid的普通初始化块--对象加载");
    }
    public Mid(){
        super();//可省略,默认会创建,向上继承父类Root的空参构造器
        System.out.println("Mid的无参构造器");
    }
    public Mid(String str){
        this();//此处不可省略,省略后空参构造器不执行
        System.out.println("Mid的带参构造器,参数值:" + str);
    }
}

class Load extends Mid{
    static{
        System.out.println("Load的静态初始化块--类加载");
    }
    {
        System.out.println("Load的普通初始化块--对象加载");
    }
    public Load(){
        super("@尚硅谷");
        System.out.println("Load的空参构造器");
    }
}


public class LoadTest {
    public static void main(String[] args) {
        new Load();
        new Load();//多次创建会发现类只会加载1次
    }
}

三、final关键字使用

1.final修饰的结构

类、方法、变量

2.作用

  • 1.final修饰类,表示此类不可以被继承(不能有子类)
    eg:String类
  • 2.final修饰方法,表示此方法不能被重写
    eg:Object中的getClass()
  • 3.final修饰变量(成员或全局变量),此时变量就变成“常量”,一旦赋值不能更改

修饰成员变量:必须在类中进行赋值(显示、构造器、代码块),不能默认赋值
修饰局部变量:一旦赋值,就不能更改
方法内声明的局部变量:在调用局部变量之前一定要赋值,且赋值后不能更改
方法的形参:在调用此方法时给形参赋值,且一旦赋值不能更改

  • 4.final与static的搭配:修饰成员变量时,此成员变量称为全局常量
    eg:public static final double PI = 3.141592653589793;
    static final int MAXIMUM_CAPACITY = 1 << 30;
//1.final修饰类
final class BrforeFinal{//无法被其他类继承,不常用此功能
}
//class FollowFinal extends BrforeFinal{}//报错

//2.final修饰方法
class FinalMethod{
    private int a;
    private int b;
    public void setA(int a) {
        this.a = a;
    }
    public void setB(int b) {
        this.b = b;
    }

    public final int sumMethod(){
        return a+b;
    }
}

class FollowMethod extends FinalMethod{
    private int c;
    public void setC(int c){
        this.c = c;
    }
 /*   public int sumMethod(){
 *       return c;
 *    }final修饰的方法不能重写
 */
}

//3.final修饰的变量
//3.1成员变量
class FinalVariable{
    int test;

    //显示赋值
    //final int HIGH;//不给final修饰的值赋值会报错
    final int MIN_SCORE = 5;//直接赋值(初始化)
    final int MAX_SCORE;

    //构造器
    public FinalVariable(){
        MAX_SCORE = 8;//构造器初始化
    }

    //public FinalVariable(int left){
    //所有构造器都需要给final修饰的变量赋值,否则报错
    //}
    public FinalVariable(int ms){
        MAX_SCORE = ms;//新创建一个对象都对MAX_SCORE重新赋一个值,保证一个对象只有一个
    }

    //代码块
    final int MID_SCORE;
    {
        MID_SCORE = 10;//代码块初始化
        //MID_SCORE = 20;//final修饰属性不能二次赋值
    }
}

//3.2局部变量
class FinalLocalVariable{
    //方法内声明的局部变量;调用局部变量前需要赋值,且一旦赋值不能更改
    public void method(){
        final int  number = 10;
        //number++;//不能修改
    }
    //方法的形参
    public void method(final int number){
        //number++;//调用方法时给形参赋值,赋值后不能进行修改
    }
}

//4.static和final的搭配
//public static final double PI = 3.141592653589793;//全局常量

public class FinalExer {
    public static void main(String[] args) {
        FinalVariable fv = new FinalVariable();
        fv.test = 10;//可正常修改
        //fv.MAX_SCORE = 10;//不能修改
    }
}

四、abstract关键字及抽象类和抽象方法

1.抽象类

有些父类设计的比较抽象,使其没有具体的实例(无法创建合适的实例),给一个类加上标识,使这个类不能实例化,这样的类被称为抽象类
eg:三角形类、长方形类、圆形类都可以包含在一个几何图形类中,但几何图形类又不便于创建实例,故需将几何图形类创建为抽象类(无法创建实例)

2.抽象方法

只有方法签名,没有方法体的方法就是抽象方法(Java规定包含抽象方法的类必须是抽象类)
eg:各种图形类有共同需求,如求周长、求体积,这些共同特征(方法)抽取到同一个父类,但这些方法又无法在父类具体实现,需交给对应子类,则父类在声明方法时,就只有方法签名而没有方法体(抽象方法)

3.格式

权限修饰符 abstract class 类名{//类体}
权限修饰符 abstract 返回值类型 方法名();//无方法体{}

注意:
1.抽象类中是包含构造器的,因为子类实例化会直接或间接调用
2.抽象类中可以没有抽象方法,但抽象方法必须在抽象类中
3.抽象方法的功能是确定的(方法声明),只是无法确定具体实现方式(方法体)
4.子类必须重写(实现)父类中所有抽象方法之后,才能实例化,否则该子类还是抽象类(抽象父类b如果也继承于一个抽象父类a,则b的子类c除了重写b的抽象方法外,还需重写a的抽象方法)

4.不适用场景:

  • 1.abstract不能修饰属性、构造器、代码块等结构
  • 2.abstract不能修饰私有方法(private)、静态方法(static)、final修饰的方法、final修饰的类

abstract不适用原因:
私有方法不能更改;静态方法能通过类调用,但是抽象方法不能通过类调用(无方法体),相矛盾;
final修饰的类不能被继承;final修饰的方法不能被重写。

abstract class Geometric{//抽象类,可以有子类
    private String name;

    public Geometric(){}
    public Geometric(String name){
        this.name = name;
    }

    public abstract void calculatePerimeter();//计算周长,抽象方法
    //{}不需要方法体
    public abstract void calculateArea();//计算面积,抽象方法
    //{}不需要方法体
}

class Triangle extends Geometric{//三角形
    private double high;
    private double edge;

    public Triangle(double high,double edge){
        //super();父类默认空构造器,如未单独创建带参或显示创建无参构造器,则系统会默认创建(子类调用父类构造器必须使用super(参数)结构)
        super("三角形");
        this.high = high;
        this.edge = edge;
    }

    //public abstract void calculatePerimeter();//只能声明在抽象类中

    public void calculatePerimeter(){//此处不为方法重写(Override)而为实现(Implement),但是表现一致
        System.out.println("计算三角形周长");
    }
    public void calculateArea(){
        System.out.println("计算三角形面积");
    }
    //必须实现父类中所有抽象方法,否则该类仍为抽象类,需加abstract,不加则报错
}

class Circle extends Geometric{//圆形
    double radius;

    public Circle(double radius){
        super("圆形");
        this.radius = radius;
    }

    public void calculatePerimeter(){
        System.out.println("计算圆形周长");
    }
    public void calculateArea(){
        System.out.println("计算圆形面积");
    }
}

class Rectangle extends Geometric{//矩形
    private double edge;

    public Rectangle(double edge){
        super("矩形");
        this.edge = edge;
    }

    public void calculatePerimeter(){
        System.out.println("计算矩形周长");
    }
    public void calculateArea(){
        System.out.println("计算矩形面积");
    }
}


public class AbstractExer {
    public static void main(String[] args) {
        //Geometric geometric = new Geometric();//抽象类不能实例化
        Triangle triangle = new Triangle(5,5);
        Circle circle = new Circle(5);
        Rectangle rectangle = new Rectangle(5);
    }
}

五、interface关键字及接口

-->举例见KeyWords包中的InterfaceExer类

接口与类是实现关系

1.理解

接口的本质是契约、标准、规范(USB通用接口);可以理解为接口定义了一段代码,这段代码可以让其他类使用,且其他类使用时都遵守接口中所规定的内容

2.接口内部说明

可以声明:

  • 属性:必须使用public、static、final修饰
  • 方法:jdk8之前,声明抽象方法,修饰为public abstract
  • jdk8,声明静态方法、默认方法
    1.接口声明的静态方法只能通过接口调用,不能通过接口实现类调用;
    2.接口声明方法可以被实现类继承,实现类若未重写此方法,则调用接口中声明的默认方法,若已重写,则调用自己重写的方法;
    3.类实现了两个接口,且两个接口中定义了同名同参数的默认方法,则实现类在没有重写此两个接口默认方法情况下,会报错;此时实现类必须重写接口中定义的同名同参数方法;
    4.子类(或实现类)继承了父类并实现了接口类,父类和接口类中声明了同名同参数的方法(其中接口的方法是默认方法),默认情况下,子类(或实现类)在没有重写此方法的情况下,调用的是父类的方法(类优先原则)
  • jdk9,声明私有方法
    让类中其他方法能调用且又不被暴露

不可以声明:构造器、代码块等

    格式:class A extends SuperA implements B,C{}
        A相较于SuperA来说,叫子类;
        A相较于B,C来说,叫做实现类

3.注意

1.类可以实现多个接口
2.类针对接口的多实现,一定程度上弥补了类的单继承的局限性
3.类必须将实现的接口中的所有抽象方法都重写(或实现),方可实例化,否则此实现类必须声明为抽象类
4.接口与接口的关系:继承关系,且可以多继承
5.接口的多态性:接口名 变量名 = new 实现类对象(接口没有构造器,不能实例化)

4.接口与抽象类的异同:

同:都可以声明抽象方法;都不能实例化
异:抽象类一定有构造器,接口没有构造器;类与类间是继承关系,类与接口间是实现关系,接口与接口间是多继承关系

//接口
interface Computer{
    public static final String NAME = "Electronic book";
    //public static final可以省略,在接口中创建属性时会自动增加在类型前,使其成为全局常量
    String TYPE_OF_READING = "graph";//图形

    //省略public abstract
    void browse();//{}抽象方法,不需要方法体
    static void listen(){//静态方法,也可换为default,为默认方法
        System.out.println("用电脑听");
    }
    private static void write(){//私有方法
        System.out.println("用电脑写");
    }
    static void getWrite(){
        write();
    }
}

interface Paper{
    String NAME = "Paper book";
    String TYPE_OF_READING = "text";//文字

    void read();

    default void listen(){//默认方法,也可换为static,为静态方法
        System.out.println("听老师讲课");
    }
}

//接口的继承性(多重继承)
interface Read extends Computer,Paper{
    void study();
}


//类实现接口
class Teacher implements Computer,Paper{//类可以实现多个接口
    @Override
    public void browse() {
        System.out.println("老师上网查教材");
    }

    @Override
    public void read() {
        System.out.println("老师阅读教科书");
    }
}

class Pupil implements Read{
    @Override
    public void browse() {
        System.out.println("小学学生上网查答案");
    }
    @Override
    public void read() {
        System.out.println("小学学生阅读笔记");
    }
    @Override
    public void study() {
        System.out.println("小学学生学习取得好成绩");
    }
}

class Undergraduate implements Read{
    public void browse() {
        System.out.println("大学生上网查资料");
    }
    public void listen(){
        System.out.println("听教授讲课");
    }
    @Override
    public void read() {
        System.out.println("大学生阅读论文");
    }
    @Override
    public void study() {
        System.out.println("大学生不挂科");
    }
}

public class InterfaceExer{
    public static void main(String[] args) {
        System.out.println("--------接口的属性(全局常量)--------");
        //接口中定义的属性为全局常量
        System.out.println(Computer.TYPE_OF_READING);
        //Computer.TYPE_OF_READING = "E-Book";//全局常量不能更改
        System.out.println(Computer.NAME);
        System.out.println(Paper.NAME);
        System.out.println(Paper.TYPE_OF_READING);

        System.out.println("--------接口的多态性--------");
        //多态性,接口没有构造器,不能实例化,所以使用接口的实现类进行实例化
        //1.创建 接口实现类 的对象
        Read pupil = new Pupil();
        pupil.browse();
        pupil.read();
        pupil.study();
        //2.创建 接口实现类 的匿名对象(没有对象名)
        (new Undergraduate()).browse();
        new Undergraduate().read();//可不加括号
        new Undergraduate().study();

        //3.创建 接口匿名实现类 的对象
        Computer computer = new Computer() {
            @Override
            public void browse() {
                System.out.println("使用电脑冲浪");
            }
        };
        computer.browse();
        //4.创建 接口匿名实现类 的匿名对象
        new Computer(){
            public void browse(){
                System.out.println("使用电脑上网");
            }
        }.browse();

        System.out.println("--------接口中的静态、默认、私有方法--------");
        //接口中的静态、默认、私有方法
        //Teacher.listen;不能通过接口实现类调用
        Computer.listen();//静态方法,只能通过接口调用
        pupil.listen();//默认方法,通过对象调用;实现类未重写
        new Undergraduate().listen();//默认方法,通过对象调用(此处匿名对象);实现类重写
        Computer.getWrite();//私有方法,可以在原类中创建公用方法调用私有方法,不过私有方法主要作用是给类中其他方法使用
    }
}

六、内部类

在字节码文件中内部类使用 ‘$’ 表示,若有多个同名的则在 ‘$’ 后加序号1,2,3

1.概念

将一个类A定义在另一个类B里,里面的类A就称为内部类,类B称为外部类

2.为什么需要内部类

当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整结构B又只为外部事务A提供服务,不在其他地方单独使用,则整个内部的完整结构B最好使用内部类(高内聚,低耦合)

示例:
Thread类内部声明了State类,表示线程的生命周期
HashMap类中声明了Node类,表示封装的key和value

3.分类

3.1 成员内部类:直接声明在外部类的里面

  • 使用static修饰:静态的成员内部类
  • 不使用static修饰:非静态的成员内部类

3.2 局部内部类:声明在方法内、构造器内、代码块内的内部类

  • 匿名的成员内部类
  • 非匿名的成员内部类

4.成员内部类解析

  • 从类结构的角度:
    可以声明属性、方法、构造器、代码块、内部类等结构;可以声明父类;可以实现接口;可以使用final修饰;可以使用abstract修饰
  • 从外部类的角度:
    在内部可以调用外部类的结构,如属性、方法等;除了使用public、缺省权限修饰之外,还可以使用private、protected修饰;可以使用static修饰
结构:
1.声明内部类:class 类名{//外部类
                static class 类名{}//静态内部类

                class 类名{}//非静态内部类

                void method(){//方法(构造器、代码块结构同)
                     class 类名{}//局部内部类
                }
              }

5.内部类的实例

  • 静态内部类:
    外部类名.内部类名 变量名 = new 外部类名.内部类名();
  • 非静态内部类:
    外部类名 变量名1 = new 外部类名();
    外部类名.内部类名 变量名2 = 变量名1.new 内部类名();
  • 成员内部类成员调用外部类成员:
    内部类成员变量(方法)与外部类成员变量(方法)重名时,在内部类调用外部类成员结构为:外部类名.this.外部类变量名(外部类方法名());
  • 局部内部类使用:通常应用于接口的匿名实现类的匿名对象

七、枚举类

1.概念

本质也是一种类,但是此类的对象是有上限的、固定的几个,不能随意创建
eg:星期(一七);性别(男女);月份(一月~七月)……

2.应用

如果开发中针对某个类,其实例是确定个数的,则推荐将此类声明为枚举类
如果枚举类实例只有一个,则可以看作单例实现方法

jdk5.0之前—在类中定义好实例并全局化,外部可使用但无法修改

public class SeasonTest {
    public static void main(String[] args) {
        //Season season = new Season();外部无法创建

        System.out.println(Season.SPRING.toString());
        System.out.println(Season.SUMMER);//此种写法相当于省略toString;若类中没有重写toString,则返回对象地址,否则返回重写后方法内容
        System.out.println(Season.AUTUMN);
        System.out.println(Season.WINTER);

        Season.SPRING.toString();
        System.out.println(Season.SPRING.getSEASON_DESC());
    }
}


class Season{
    //2.声明当前类的对象的实例变量,使用private final修饰
    private final String SEASON_NAME;
    private final String SEASON_DESC;

    //1.私有化构造器;让外部无法创建新的对象,只能使用已经创建好的对象
    private Season(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }

    //3.提供实例化get方法
    public String getSEASON_NAME(){
        return SEASON_NAME;
    }
    public String getSEASON_DESC(){
        return SEASON_DESC;
    }

    //4.创建当前类的实例,使用public static final修饰;外部无法更改,且可以直接调用
    public static final Season SPRING = new Season("春天","春暖花开");
    public static final Season SUMMER = new Season("夏天","夏日炎炎");
    public static final Season AUTUMN = new Season("秋天","秋高气爽");
    public static final Season WINTER = new Season("冬天","冬雪纷飞");

    @Override
    public String toString() {
        return "Season{" +
                "SEASON_NAME='" + SEASON_NAME + '\'' +
                ", SEASON_DESC='" + SEASON_DESC + '\'' +
                '}';
    }
}

jdk5.0中使用enum关键字定义枚举类—举例见KeyWords包中的SeasonTest1类
enum关键字:
使用enum关键字定义的枚举类,默认其父类是java.lang.Enum类
使用enum关键字定义的枚举类,不要再显示定义其父类,否则报错(已经有父类)

public class SeasonTest1 {
    public static void main(String[] args) {
        System.out.println(Season1.SPRING.toString());
        System.out.println(Season1.SUMMER);
        System.out.println(Season1.AUTUMN);
        System.out.println(Season1.WINTER);
        //在enum定义的枚举类的父类Enum中,toString方法默认返回的是常量名(对象名),可以重写此方法(参见SeasonTest)

        //name(),返回当前对象名
        System.out.println(Season1.SPRING.name());

        //values(),返回枚举类型对象数组,方便遍历所有枚举值,声明及定义于ElementType类中
        Season1[] values = Season1.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
        }

        System.out.println(Season1.SPRING.getSEASON_DESC());
    }
}

//jdk5.0使用关键字定义枚举类
enum Season1{
    //1.必须在枚举类开始声明对象(若干),对象之间使用英文逗号','隔开
    //在声明对象时候多于部分"public static final 类名"和" = new 类名"可以省略;仅保留对象名和构造参数
    //public static final Season1 SPRING = new Season1("春天","春暖花开");
    SPRING("春天","春暖花开"),
    SUMMER("夏天","夏日炎炎"),
    AUTUMN("秋天","秋高气爽"),
    WINTER("冬天","冬雪纷飞");

    //2.声明当前类的对象的实例变量,使用private final修饰
    private final String SEASON_NAME;
    private final String SEASON_DESC;

    //3.私有化构造器;让外部无法创建新的对象,只能使用已经创建好的对象
    private Season1(String SEASON_NAME,String SEASON_DESC){
        this.SEASON_NAME = SEASON_NAME;
        this.SEASON_DESC = SEASON_DESC;
    }

    //3.提供实例化get方法
    public String getSEASON_NAME(){
        return SEASON_NAME;
    }
    public String getSEASON_DESC(){
        return SEASON_DESC;
    }
}

八、注解

1.概念

从jdk5.0引入,以"@注解名"在代码中存在,如:@Override、@Deprecated;可以在类编译、运行时进行加载,体现不同功能

2.使用

  • 1.常用注解
    @Override:限定重写父类方法,该注解只能用于方法(当重写方法步骤出现错误时会提醒)
    @Deprecated:表示已过时(不推荐用但是可以用)
    @SuppressWarnings:表示抑制编译器警告
  • 2.自定义注解:
    新建一个Annotation(eg:MyAnnotation)用于某些特殊功能,在类中使用MyAnnotation
  • 3.元注解:对现有注解进行解释说明的注解

九、单元测试

  • 需要导入的包:junit-4.12.jar、hamcrest-core-1.3.jar
  • 单元测试的作用:可以不使用main方法,直接测试代码的运行情况
  • 注意:
    需要正确编写单元测试方法,需要满足两个条件,
    1.所在类必须是public的、非抽象的、包含唯一无参构造器的
    2.@Test所标记的方法本身必须是public、非抽象的、非静态的、无返回值(void)、()无参数的
  • 单元测试方法和main方法类似,是一个程序执行的入口,不需要返回任何值,所以他们的返回值类型都是void
  • 可以创建一个有返回值方法,然后在单元测试方法中调用并创建变量接收返回值

十、包装类

  1. 概念:基本数据类型可以直接使用,效率较高,但是有时我们需要将其作为引用数据类型使用,就需要包装类
  • byte–Byte、short–Short、int–Integer、long–Long、float–Float、double–Double==父类是Number
  • boolean–Boolean、char–Character
  1. 理解:将基本数据类型创建的属性外面套一个类结构,使基本数据具有引用数据类型的特点
  2. 为什么需要进行数据转换:
    1.在某些情况下,需要使用基本数据类型对应的包装类对象,所以将起转换为包装类
    2.对于包装类,我们使用的是对象,不能进行基本运算(±*/等),为了能正常运算,需要将其转为基本数据类型
  3. 注意:
    1.装箱(基本数据类型–包装类):jdk9之后,使用构造器创建包装类对象的方法被替代了,改为使用valueOf方法
    Integer integer = Integer.valueOf(33);
    2.装箱(包装类–基本数据类型):使用xxxValue方法将其转换为相应类型值,在进行计算
    Integer integer = Integer.valueOf(33);
    int integerNum = integer.intValueOf();
    3.jdk5.0之后有了自动装箱、自动拆箱特性
  4. String类、基本数据类型和包装类的相互转换
    • 1.String类–基本数据类型:
      1.1 String类的valueOf(数据)方法
      1.2 数据+“”
    • 2.基本数据类型–String类:
      2.1 通过相应包装类的parseXxx(String)静态方法
      2.2 通过包装类构造器(eg:boolean b = new Boolean(“true”))
    • 3.基本数据类型–包装类:
      3.1 构造器
      3.2 字符串参数(eg:Float f = new Float(“3.14F”))
      3.3 静态方法(eg:Integer integer = integer.valueOf(12))
      3.4 自动装箱
    • 4.包装类–基本数据类型:
      4.1 调用包装类的方法:xxxValue()
      4.2 自动拆箱
    • 5.包装类–String类:
      5.1 包装类对象的toString()方法
      5.2 调用包装类的toString(形参)方法
    • 6.String类–包装类
      6.1 构造器
      6.2 字符串参数(eg:Float f = new Float(“3.14F”))
      6.3 静态方法(eg:Integer integer = integer.valueOf(12))
      6.4 自动装箱
  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值