07-java面向对象:枚举、包装类、抽象类

目录

7.2 枚举

7.2.1 概述

7.2.2 JDK1.5之前

7.2.3 JDK1.5之后

1、enum关键字声明枚举

2、枚举类的要求和特点

3、枚举类型常用方法

7.3 包装类

7.3.1 包装类

7.3.2 装箱与拆箱

7.3.3 包装类的一些API

1、基本数据类型和字符串之间的转换

2、数据类型的最大最小值

3、字符转大小写

4、整数转进制

5、比较的方法

7.3.4 包装类对象的特点

1、包装类缓存对象

2、类型转换问题

3、包装类对象不可变

7.4 抽象类

7.4.1 由来

7.4.2 语法格式

7.3.3 注意事项

7.3.4 修饰符一起使用问题?

7.2 枚举

7.2.1 概述

枚举类型本质上也是一种类,只不过是这个类的对象是固定的几个,而不能随意让用户创建。

在JDK1.5之前,需要程序员自己通过特殊的方式来定义枚举类型。

在JDK1.5之后,Java支持enum关键字来快速的定义枚举类型。

枚举在应用的时候直接获取创建好的对象即可,不需要在new了

7.2.2 JDK1.5之前

在JDK1.5之前如何声明枚举类呢?

  • 构造器加private私有化

  • 本类内部创建一组常量对象,并添加public static修饰符,对外暴露这些常量对象

示例代码:

public class Season2 {

    //设置固定好的4个量 常量
    //把小写转化为大写的快捷键 ctrl+shift+u
    public final static Season2 SPRING = new Season2("春天");
    public final static Season2 SUMMER = new Season2("夏天");
    public final static Season2 AUTUMN= new Season2("秋天");
    public final static Season2 WINTER = new Season2("冬天");

    //重写toString
    //1.定义一个描述
    private String description;
    //无参
    public Season2() {
    }
    //有参
    public Season2(String description) {
        this.description = description;
    }
    //2.get/set方法
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    //3.用构造器写出来
    @Override
    public String toString() {
        return "Season2{" +
                "description='" + description + '\'' +
                '}';
    }
}

7.2.3 JDK1.5之后

1、enum关键字声明枚举
【修饰符】 enum 枚举类名{
    常量对象列表
}
​
【修饰符】 enum 枚举类名{
    常量对象列表;
    
    其他成员列表;
}

示例代码:

public enum SeasonAfter5 {
    SPRING("春天后"),SUMMER("夏天后"),AUTUMN("秋天后"),WINTER;

    //常量  建议使用常量 不是必须
    private final String description;

    //构造器
    SeasonAfter5() {
        description="";
    }

    SeasonAfter5(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "SeasonAfter5{" +
                "description='" + description + '\'' +
                '}';
    }
}
2、枚举类的要求和特点

枚举类的要求和特点:

  • 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。

  • 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。

  • 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数,

  • 如果枚举类需要的是有参构造,需要手动定义,有参构造的private可以省略,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。

  • 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。

  • JDK1.5之后switch,提供支持枚举类型,case后面可以写枚举常量名。

  • 枚举类型如有其它属性,建议(不是必须)这些属性也声明为final的,因为常量对象在逻辑意义上应该不可变。

示例代码:

public enum Color7 {
    RED("红色",1),GREEN,BLUE,BLACK,PINK("粉色",1);

    private final String description;
    private int flag;

    Color7() {
        description="";
    }

    Color7(String description, int flag) {
        this.description = description;
        this.flag = flag;
    }

    @Override
    public String   toString() {
        return "Color7{" +
                "description='" + description + '\'' +
                ", flag=" + flag +
                '}';
    }
}
3、枚举类型常用方法
1.String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法!
2.String name():返回的是常量名(对象名)
3.int ordinal():返回常量的次序号,默认从0开始
4.枚举类型[] values():返回该枚举类的所有的常量对象,返回类型是当前枚举的数组类型,是一个静态方法
5.枚举类型 valueOf(String name):根据枚举常量对象名称获取枚举对象

示例代码:

public class PackApi {
    public static void main(String[] args) {
        System.out.println("int类型的最大值:" + Integer.MAX_VALUE);
        System.out.println("int类型的最小值:" + Integer.MIN_VALUE);
        System.out.println("-----------------");
        System.out.println("long类型的最大值:" + Long.MAX_VALUE);
        System.out.println("long类型的最小值:" + Long.MIN_VALUE);
//        转换进制的方法
//        二进制
        System.out.println(Integer.toBinaryString(20));
//        八进制
        System.out.println(Integer.toOctalString(20));
//        十六进制
        System.out.println(Integer.toHexString(20));
//        将纯数字字符串转换为基本数据类型的值
        System.out.println("___________________");
        String str1 = "Hello";
        String str2 = "Hello123";
        String str3 = "123Hello";
        String str4 = "123";
//        System.out.println(Integer.parseInt(str1));
//        System.out.println(Integer.parseInt(str2));
//        System.out.println(Integer.parseInt(str3));
        System.out.println(Integer.parseInt(str4));
        String str5 = "123.45";
        double d1 = Double.parseDouble(str5);
        double d2 = Double.valueOf(str5);
        System.out.println(d1);
        System.out.println(d2);
//        将字符串进行转换大小写
        char cha1 = 'a';
        char cha2 = Character.toUpperCase(cha1);
        char cha3 = 'A';
        char cha4 = Character.toLowerCase(cha3);
        System.out.println(cha2);
        System.out.println(cha4);
//        比较大小
//        如果a>b ,用正数表示 1
//        如果a<b ,用负数表示 -1
//        如果a=b ,用0来表示结果
        double a = 15;
        double b = 15;
        System.out.println(Double.compare(a, b));
    }
}

7.3 包装类

7.3.1 包装类

Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而当要使用只针对对象设计的API或新特性(例如泛型),那么基本数据类型的数据就需要用包装类来包装。

序号基本数据类型包装类(java.lang包)
1byteByte
2shortShort
3intInteger
4longLong
5floatFloat
6doubleDouble
7charCharacter
8booleanBoolean
9voidVoid

7.3.2 装箱与拆箱

装箱:把基本数据类型转为包装类对象。

转为包装类的对象,是为了使用专门为对象设计的API和特性

拆箱:把包装类对象拆为基本数据类型。

转为基本数据类型,一般是因为需要运算,Java中的大多数运算符是为基本数据类型设计的。比较、算术等

基本数值---->包装对象

Integer obj1 = new Integer(4);//使用构造函数函数
Integer obj2 = Integer.valueOf(4);//使用包装类中的valueOf方法

包装对象---->基本数值

Integer obj = new Integer(4);
int num1 = obj.intValue();

JDK1.5之后,可以自动装箱与拆箱。

注意:只能与自己对应的类型之间才能实现自动装箱与拆箱。

Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
//加法运算完成后,再次装箱,把基本数值转成对象。
Integer i = 1;
Double d = 1;//错误的,1是int类型

7.3.3 包装类的一些API

1、基本数据类型和字符串之间的转换

(1)把基本数据类型转为字符串

int a = 10;
//String str = a;//错误的
//方式一:
String str = a + "";
//方式二:
String str = String.valueOf(a);

(2)把字符串转为基本数据类型

String转换成对应的基本类型 ,除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型,例如:

  • public static int parseInt(String s):将字符串参数转换为对应的int基本类型。

  • public static long parseLong(String s):将字符串参数转换为对应的long基本类型。

  • public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。

或把字符串转为包装类,然后可以自动拆箱为基本数据类型

  • public static Integer valueOf(String s):将字符串参数转换为对应的Integer包装类,然后可以自动拆箱为int基本类型

  • public static Long valueOf(String s):将字符串参数转换为对应的Long包装类,然后可以自动拆箱为long基本类型

  • public static Double valueOf(String s):将字符串参数转换为对应的Double包装类,然后可以自动拆箱为double基本类型

注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出java.lang.NumberFormatException异常。

int a = Integer.parseInt("整数的字符串");
double d = Double.parseDouble("小数的字符串");
boolean b = Boolean.parseBoolean("true或false");
​
int a = Integer.valueOf("整数的字符串");
double d = Double.valueOf("小数的字符串");
boolean b = Boolean.valueOf("true或false");
2、数据类型的最大最小值
Integer.toBinaryString(int i) 
Integer.toHexString(int i)
Integer.toOctalString(int i)
Integer.MAX_VALUE和Integer.MIN_VALUE
Long.MAX_VALUE和Long.MIN_VALUE
Double.MAX_VALUE和Double.MIN_VALUE
3、字符转大小写
Character.toUpperCase('x');
Character.toLowerCase('X');
4、整数转进制
Integer.toBinaryString(int i) 
Integer.toHexString(int i)
Integer.toOctalString(int i)
5、比较的方法
Double.compare(double d1, double d2)
Integer.compare(int x, int y) 

7.3.4 包装类对象的特点

1、包装类缓存对象
包装类缓存对象
Byte-128~127
Short-128~127
Integer-128~127
Long-128~127
Float没有
Double没有
Character0~127
Booleantrue和false
Integer a = 1;
Integer b = 1;
System.out.println(a == b);//true
​
Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false
​
Integer m = new Integer(1);//新new的在堆中
Integer n = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(m == n);//false
​
Integer x = new Integer(1);//新new的在堆中
Integer y = new Integer(1);//另一个新new的在堆中
System.out.println(x == y);//false
Double d1 = 1.0;
Double d2 = 1.0;
System.out.println(d1==d2);//false 比较地址,没有缓存对象,每一个都是新new的
2、类型转换问题
Integer i = 1000;
double j = 1000;
System.out.println(i==j);//true  会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
Integer i = 1000;
int j = 1000;
System.out.println(i==j);//true 会自动拆箱,按照基本数据类型进行比较
Integer i = 1;
Double d = 1.0
System.out.println(i==d);//编译报错
3、包装类对象不可变
public class TestExam {
    public static void main(String[] args) {
        int i = 1;
        Integer j = new Integer(2);
        Circle c = new Circle();
        change(i,j,c);
        System.out.println("i = " + i);//1
        System.out.println("j = " + j);//2
        System.out.println("c.radius = " + c.radius);//10.0
    }
    
    /*
     * 方法的参数传递机制:
     * (1)基本数据类型:形参的修改完全不影响实参
     * (2)引用数据类型:通过形参修改对象的属性值,会影响实参的属性值
     * 这类Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了
     */
    public static void change(int a ,Integer b,Circle c ){
        a += 10;
//      b += 10;//等价于  b = new Integer(b+10);
        c.radius += 10;
        /*c = new Circle();
        c.radius+=10;*/
    }
}
class Circle{
    double radius;
}

7.4 抽象类

7.4.1 由来

抽象:即不具体、或无法具体

例如:当我们声明一个几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长、获取图形详细信息。那么这些共同特征应该抽取到一个公共父类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类

7.4.2 语法格式

  • 抽象方法:被abstract修饰没有方法体的方法。

  • 抽象类:被abstract修饰的类。

抽象类的语法格式

【权限修饰符】 abstract class 类名{
    
}
【权限修饰符】 abstract class 类名 extends 父类{
    
}

抽象方法的语法格式

【其他修饰符】 abstract 返回值类型 方法名(【形参列表】);

注意:抽象方法没有方法体

代码举例:

public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal {
    public void run (){
        System.out.println("小猫吃鱼和猫粮");   
    }
}
public class CatTest {
     public static void main(String[] args) {
        // 创建子类对象
        Cat c = new Cat(); 
       
        // 调用eat方法
        c.eat();
    }
}

此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

7.3.3 注意事项

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。

    理解:子类的构造方法中,有默认的super()或手动的super(实参列表),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

7.3.4 修饰符一起使用问题?

外部类成员变量代码块构造器方法局部变量内部类(后面讲)
public××
protected×××
缺省××
private×××
static×××
final××
abstract××××
native××××××

不能和abstract一起使用的修饰符?

(1)abstract和final不能一起修饰方法和类

(2)abstract和static不能一起修饰方法

(3)abstract和native不能一起修饰方法

(4)abstract和private不能一起修饰方法

static和final一起使用:

(1)修饰方法:可以,因为都不能被重写

(2)修饰成员变量:可以,表示静态常量

(3)修饰局部变量:不可以,static不能修饰局部变量

(4)修饰代码块:不可以,final不能修改代码块

(5)修饰内部类:可以一起修饰成员内部类,不能一起修饰局部内部类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值