目录
9.3在jdk5.0时,加入使用 enum定义枚举类。步骤如下:
方式 1:使用 parseXxx 静态方法将字符串参数转换为对应的基本类型(除了 Character 类)
Integer.toString(int i, int radix)方法将十进制数decimal转换为指定进制radix的字符串表示
一.static(静态的)
1.1 static使用范围
在 Java 类中,可用 static 修饰属性、方法、代码块、内部类
被修饰后的成员具备以下特点:
随着类的加载而加载
优先于对象存在
修饰的成员,被所有对象所共享
访问权限允许时,可不创建对象,直接被类调用
1.2静态属性语法格式与静态方法格式
使用 static 修饰的成员变量就是静态变量(或类变量、类属性)
[修饰符] class 类{
[其他修饰符] static 数据类型 变量名;
}
用 static 修饰的成员方法就是静态方法。
[修饰符] class 类{
[其他修饰符] static 返回值类型 方法名(形参列表){
方法体
}
}
1.3 静态变量与静态方法的特点
静态变量
静态变量的默认值规则和实例变量一样。
静态变量值是所有对象共享。
静态变量在本类中,可以在任意方法、代码块、构造器中直接使用。
如果权限修饰符允许,在其他类中可以通过“类名.静态变量”直接访问,也可以通过 “对象.静态变量”的方式访问(但推荐使用类名.静态变量的方式)。
静态变量的 get/set 方法也静态的,当局部变量与静态变量重名时,使用“类名.静态变量”进行区分。
静态变量的默认值
基本数据类型:
byte
:默认值为0。short
:默认值为0。int
:默认值为0。long
:默认值为0L。float
:默认值为0.0f。double
:默认值为0.0d。boolean
:默认值为false。char
:默认值为'\u0000'(空字符)。引用类型:
- 默认值为null,表示没有引用任何对象。
数组:
- 数组的每个元素都会根据其类型自动初始化为默认值。
静态变量:
类中的属性使用static进行修饰。 对比静态变量与实例变量:
① 个数
静态变量:在内存空间中只有一份,被类的多个对象所共享。
实例变量:类的每一个实例(或对象)都保存着一份实例变量。(有几个对象有多少实列变量)
② 内存位置
静态变量:jdk6及之前:存放在方法区。 jdk7及之后:存放在堆空间
实例变量:存放在堆空间的对象实体中。
③ 加载时机
静态变量:随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份。
实例变量:随着对象的创建而加载。每个对象拥有一份实例变量。
④ 调用者
静态变量:可以被类直接调用,也可以使用对象调用。
实例变量:只能使用对象进行调用。
⑤ 判断是否可以调用
从生命周期的角度解释
类变量 实例变量
类 yes no
对象 yes yes
⑥ 消亡时机
静态变量:随着类的卸载而消亡
实例变量:随着对象的消亡而消亡
静态方法
静态方法在本类的任意方法、代码块、构造器中都可以直接被调用。
只要权限修饰符允许,静态方法在其他类中可以通过“类名.静态方法“的方式调用。也可以通过”对象.静态方法“的方式调用(但推荐使用类名.静态方法的方式)。
在 static 方法内部只能访问类的 static 修饰的属性或方法,不能访问类的非 static 的结 构。
静态方法可以被子类继承,但不能被子类重写。
因为不需要实例就可以访问 static 方法,因此 static 方法内部不能有 this,也不能有 super。如果有重名问题,使用“类名.”进行区别。
随着类的加载而加载
可以通过“类.静态方法”的方式,直接调用静态方法
静态方法内可以调用静态的属性或静态的方法。(不可以调用非静态的结构。(如:属性、方法)
判断是否可以调用
类方法 实例方法
类 yes no
对象 yes yes
static修饰的方法内,不能使用this和super
补充:在类的非静态方法中,可以调用当前类中的静态结构(属性、方法)或非静态结构(属性、方法)
1.4变量的分类
方式1:按照数据类型:基本数据类型、引用数据类型
方式2:按照类中声明的位置:
成员变量:按照是否使用static修饰进行分类:
使用static修饰的成员变量:静态变量、类变量
不使用static修饰的成员变量:非静态变量、实例变量
局部变量概念:方法内、方法形参、构造器内、构造器形参、代码块内的变量等。
1.4代码解析
public class Accoraed {
public static void main(String[] args) {
Bank accoraed = new Bank();
System.out.println(accoraed);
Bank accoraed1 = new Bank();
accoraed1.setPassword("000000");
System.out.println(accoraed1);
Bank accoraed2 = new Bank();
accoraed2.setBalance(5000);
System.out.println(accoraed2.getBalance());
Bank.setInterestRate(0.045);
Bank.setMinBalance(10);
System.out.println("银行存款的利率为:" + Bank.getInterestRate());
System.out.println("银行存款的最低余额为:" + Bank.getMinBalance());
}
}
/**
* packageName exer14.test1
*
* @author 曦
* @version 1.0
* @className Bank
* @date 2024/10/29 18:25
* @description TODO 编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些属性的方法。
* 账号要自动生成。
* 编写主类,使用银行账户类,输入、输出3个储户的上述信息。
*/
public class Bank {
private int id;//账号
private String password;//密码
private double balance;//存款余额
private static double interestRate = 0.043;//利率
private static double minBalance = 1.0;//最小余额
private static int init = 1001;//自动生成账号
/**
*@description TODO:
*@description : Bank
* @param :
* @param * return null
*@author 曦
*@throws
*@return {@link null}
*@date 2024/10/29 18:56
**/
public Bank() {
this.id = init++;// 使用静态变量init生成唯一账号
password = "123456";// 设置默认密码为"123456"
}
/**
*@description TODO:
*@description : Bank
* @param balance:
* @param id:
* @param password:
*@author 曦
*@throws
*@return {@link @return: null}
*@date 2024/10/29 19:44
**/
public Bank(double balance, int id, String password) {
this.balance = balance;// 设置账户余额
this.id = init++;// 使用静态变量init生成唯一账号
this.password = password;// 设置账户密码
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Bank.interestRate = interestRate;
}
public static double getMinBalance() {
return minBalance;
}
public static void setMinBalance(double minBalance) {
Bank.minBalance = minBalance;
}
/**
*@description TODO:重写toString方法
*@description : toString
* @param :
*@author 曦
*@throws
*@return {@link @return: java.lang.String}
*@date 2024/10/29 19:48
**/
@Override
public String toString() {
return "Bank{" +
"id=" + id +
", password='" + password + '\'' +
", balance=" + balance +
'}';
}
}
静态属性
private static double interestRate = 0.043;//利率
private static double minBalance = 1.0;//最小余额
private static int init = 1001;//自动生成账号
静态方法
public static double getInterestRate() {
return interestRate;
}
public static void setInterestRate(double interestRate) {
Bank.interestRate = interestRate;
}
public static double getMinBalance() {
return minBalance;
}
public static void setMinBalance(double minBalance) {
Bank.minBalance = minBalance;
}
二.单例(Singleton)设计模式
1.饿汉式
public class BankTest {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);
}
}
//饿汉式
class Bank {
//1. 类的构造器私有化
private Bank() {
}
//2. 在类的内部创建当前类的实例
//4. 此属性也必须声明为static的
private static Bank instance = new Bank();
//3. 使用getXxx()方法获取当前类的实例,必须声明为static的
public static Bank getInstance() {
return instance;
}
}
2.懒汉式
public class GirlFriendTest {
public static void main(String[] args) {
}
}
//懒汉式
class GirlFriend {
//1.类的构造器私有化
private GirlFriend() {
}
//2. 声明当前类的实例
//4. 此属性也必须声明为static的
private static GirlFriend instance = null;
//3. 通过getXxx()获取当前类的实例,如果未创建对象,则在方法内部进行创建
public static GirlFriend getInstance() {
if (instance == null) {
instance = new GirlFriend();
}
return instance;
}
}
对比
3.特点、优缺点
特点:
饿汉式:“立即加载”,随着类的加载,当前的唯一实例就创建了
懒汉式:"延迟加载",在需要使用的时候,进行创建。
优缺点:
饿汉式:
(优点)写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。 (缺点)内存中 占用时间较长。
懒汉式:
(缺点)线程不安全 (线程不安全 ,效率高)
(优点)在需要的时候进行创建,节省内存空间。
三.代码块
3.1代码块(或初始化块)的作用:
对 Java 类或对象进行初始化
3.2代码块(或初始化块)的分类
代码块只能被 static 修饰
被 static 修饰,称为静态代码块
没有使用 static 修饰的,为非静态代码块。
3.3使用:
静态代码块:
随着类的加载而执行
由于类的加载只会执行一次,进而静态代码块的执行,也只会执行一次
作用:用来初始化类的信息
内部可以声明变量、调用属性或方法、编写输出语句等操作。
静态代码块的执行要先于非静态代码块的执行
如果声明有多个静态代码块,则按照声明的先后顺序执行
静态代码块内部只能调用静态的结构(即静态的属性、方法),不能调用非静态的结构(即非静态的属性,方法)
4.2 非静态代码块:
随着对象的创建而执行
每创建当前类的一个实例,就会执行一次非静态代码块
作用:用来初始化对象的信息
内部可以声明变量、调用属性或方法、编写输出语句等操作。
如果声明有多个非静态代码块,则按照声明的先后顺序执行
非静态代码块内部可以调用静态的结构(即静态的属性、方法),也可以调用非静态的结构(即非静态 的属性、方法)
代码解析
public class BlockTest {
public static void main(String[] args) {
System.out.println(Person.info);
System.out.println(Person.info);
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.age);//1
// p1.eat();
}
}
class Person {
String name;
int age;
static String info = "我是一个人";
public void eat() {
System.out.println("人吃饭");
}
public Person() {
}
//非静态代码块
{
System.out.println("非静态代码块2");
}
{
System.out.println("非静态代码块1");
age = 1;
System.out.println("info = " + info);
}
//静态代码块
static {
System.out.println("静态代码块2");
}
static {
System.out.println("静态代码块1");
System.out.println("info = " + info);
}
}
四..属性(实例变量)赋值
4.1.给类的非静态的属性(实例变量)赋值的位置有:
① 默认初始化
② 显式初始化 或 ⑤ 代码块中初始化
③ 构造器中初始化
④ 有了对象以后,通过"对象.属性"或"对象.方法"的方法进行赋值
4.2. 执行的先后顺序
① - ②/⑤ - ③ - ④
4.3.代码解析
public class FieldTest {
public static void main(String[] args) {
Order o1 = new Order();
System.out.println(o1.orderId);//1
}
}
class Order {
int orderId = 1;
{
orderId = 2;
}
public Order() {
super();
// orderId = 3;
}
public Order(int orderId) {
this.orderId = orderId;
}
public void eat() {
sleep();
}
public void sleep() {
}
}
五.final关键字的使用
5.1 final可以用来修饰的结构
类、方法、变量
final:最终的,(即不可以修改)
5.2final修饰
final修饰类:表示此类不能被继承。
比如:String、StringBuffer、StringBuilder类
final修饰方法:表示此方法不能被重写
比如:Object类中的getClass()
final修饰变量:既可以修饰成员变量,也可以修饰局部变量。
此时的"变量"其实就变成了"常量",意味着一旦赋值,就不可更改。
final与static搭配:修饰成员变量时,此成员变量称为:全局常量。(全局常量不可以修改)
5.3final与finally与finalize
final: 最终的,(即不可以修改)
finally:异常try..catch..finally(解决异常错误)
finalize:英语单词
六.抽象类与抽象方法
6.1 abstract的概念
抽象的
6.2 abstract可以修饰
类、方法
6.3语法格式
抽象类:被 abstract 修饰的类。
抽象方法:被 abstract 修饰没有方法体的方法。
抽象类的语法格式
[权限修饰符] abstract class 类名{ }
[权限修饰符] abstract class 类名 extends 父类{ }
抽象方法的语法格式
[其他修饰符] abstract 返回值类型 方法名([形参列表]);
注意:抽象方法没有方法体
6.3abstract修饰类
abstract修饰类,此类称为抽象类
抽象类不能实例化。
抽象类中是包含构造器的,因为子类对象实例化时,需要直接或间接的调用到父类的构造器。
抽象类中可以没有抽象方法。有抽象方法所在的类,一定是抽象类。
6.4 abstract修饰方法
abstract修饰方法此方法即为抽象方法
抽象方法只有方法的声明,没有方法体。
抽象方法其功能是确定的(通过方法的声明即可确定),只是不知道如何具体实现(体现为没有方法 体)
子类必须重写父类中的所有的抽象方法之后,方可实例化。否则,此子类仍然是一个抽象类。
6.5abstract 不能修饰哪些结构
属性、构造器、代码块
6.6 abstract 不能与哪些关键字共用
不能用abstract修饰私有方法、静态方法、final的方法、final的类。
①private修饰的方法,因为私有的方法是不能重写的。
②静态的方法,abstract修饰的方法是不应该被调用的,如果方法被static修饰,就可以通过类来进行调用。
③final修饰的方法,final修饰的方法是不能再重写的。
④final修饰的类,final修饰的类是不能被继承的。
七.接口(interface)的使用
7.1接口的理解
接口的本质是契约、标准、规范,就像我们的法律一样。制定好后大家都要遵守。
即接口是一种规范
7.2接口内部结构的说明即格式
可以声明:
属性:必须使用public static final修饰
方法:jdk8之前:声明抽象方法,修饰为public abstract
接口的声明格式
[修饰符] interface 接口名{
//接口的成员列表:
// 公共的静态常量
// 公共的抽象方法
// 公共的默认方法(JDK1.8 以上)
// 公共的静态方法(JDK1.8 以上)
// 私有方法(JDK1.9 以上)
}
7.3接口与类的关系即实现
实现关系
实现格式:
1.
【修饰符】 class 实现类 implements 接口 1,接口 2,接口 3。。。{
// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
2.
【修饰符】 class 实现类 extends 父类 implements 接口 1,接口 2,接口 3。。。{
// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写 // 重写接口中默认方法【可选】
}
接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次
7.4格式
class A extends SuperA implements B,C{
}
A相较于SuperA来讲,叫做子类
A相较于B,C来讲,叫做实现类
7.5接口作用
类可以实现多个接口。
类针对于接口的多实现,一定程度上就弥补了类的单继承的局限性。
类必须将实现的接口中的所有的抽象方法都重写(或实现),方可实例化。否则,此实现类必须声明为抽象类。
7.6接口与接口的关系
继承关系,且可以多继承
7.7 接口的多态性
接口名 变量名 = new 实现类对象;
7.8抽象类和接口
共性:都可以声明抽象方法 都不能实例化
不同:
① 抽象类一定有构造器。接口没有构造器
② 类与类之间继承关系,类与接口之间是实现关系,接口与接口之间是多继承关系
7.9补充
①接口中声明的静态方法只能被接口来调用,不能使用其实现类进行调用
静态方法的声明:public static void method1()//public可以省略 { System.out.println("这是静态方法"); }
②接口中声明的默认方法可以被实现类继承,实现类在没有实现此方法的情况下, 默认调用接口中声明的默认方法。如果重写了此方法,则调用的是重写后的方法。
默认方法的声明:public default void method2()//public可以省略 { System.out.println("这是默认方法"); }
注意:
子接口重写默认方法时,default 关键字可以保留。
子类重写默认方法时,default 关键字不可以保留。
public interface USB2 { //静态常量 long MAX_SPEED = 60 * 1024 * 1024;//60MB/s //抽象方法 void in(); void out(); //默认方法 public default void start() { System.out.println("开始"); } public default void stop() { System.out.println("结束"); } //静态方法 public static void show() { System.out.println("USB 2.0 可以高速地进行读写操作"); } } public interface USB extends USB2, USB3 { @Override default void start() { System.out.println("Usb.start"); } @Override default void stop() { System.out.println("Usb.stop"); } }
③如果类实现了两个接口,而两个方法中定义了同名同参数列表的默认方法。则实现类在没有重写此两个接口默认方法的情况下,会接口冲突(当一个类同时实现了多个父接口,而多个父接口中包含方法签名相同的默认方法)。 要求:此时实现类必须要重写接口中定义的同名同参数的方法。解决方法:选择保留其中一个,通过“接口名.super.方法名"的方法选择保留哪个接口的默 认方法。
④子类(或实现类)继承了父类并实现了接口。父类和接口中声明了同名同参数的方法(其中,接口中的方法是默认方法). 默认情况下,子类(实现类)在没有重写此方法的情况下,调用的是父类中的方法。 ---- 类优先原则(当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法。)
⑤如何在子类(实现类)中调用父类或接口中被重写的方法
method3();//调用自己类中的方法,省略了this. super.method3();//调用父类中的方法 CompareA.super.method3();//调用接口CompareA中的默认方法 CompareB.super.method3();//调用接口CompareB中的默认方法
7.10总结
接口本身不能创建对象,只能创建接口的实现类对象,接口类型的变量可以与实现类 对象构成多态引用。
声明接口用 interface,接口的成员声明有限制:
(1)公共的静态常量
(2)公共的抽象方法
(3)公共的默认方法(JDK8.0 及以上)
(4)公共的静态方法(JDK8.0 及以上)
(5)私有方法(JDK9.0 及以上)
类可以实现接口,关键字是 implements,而且支持多实现。如果实现类不是抽象类, 就必须实现接口中所有的抽象方法。如果实现类既要继承父类又要实现父接口,那么继承(extends)在前,实现(implements)在后。
接口可以继承接口,关键字是 extends,而且支持多继承。
接口的默认方法可以选择重写或不重写。如果有冲突问题,另行处理。子类重写父接口的默认方法,要去掉 default,子接口重写父接口的默认方法,不要去掉 default。
接口的静态方法不能被继承,也不能被重写。接口的静态方法只能通过“接口名.静态 方法名”进行调用。
八.内部类
8.1内部类定义即格式
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass),类B则称为外部类 (OuterClass)。
语法格式:
[修饰符] class 外部类{
[其他修饰符] [static] class 内部类{ }
}
8.2分类
内部类的分类:
成员内部类:直接声明在外部类的里面。
使用static修饰的:静态的成员内部类
不使用static修饰的:非静态的成员内部类
局部内部类:声明在方法内、构造器内、代码块内的内部类
匿名的局部内部类
非匿名的局部内部类
8.3成员内部类的理解+实例化静态内部类和实例化非静态
从类的角度看:
内部可以声明属性、方法、构造器、代码块、内部类等结构
此内部类可以声明父类,可以实现接口
可以使用final修饰
可以使用abstract修饰
从外部类的成员的角度看:
在内部可以调用外部类的结构。比如:属性、方法等
可以使用public、缺省权限修饰之外,还可以使用private、protected修饰
可以使用static修饰
实例化静态内部类
外部类名.静态内部类名 变量 = 外部类名.静态内部类名();
变量.非静态方法();
实例化非静态内部类
外部类名 变量 1 = new 外部类();
外部类名.非静态内部类名 变量 2 = 变量 1.new 非静态内部类名();
变量 2.非静态方法();
代码案列
public class TestMemberInnerClass { public static void main(String[] args) { //创建静态内部类实例,并调用方法 Outer.StaticInner inner = new Outer.StaticInner(); inner.inFun(); //调用静态内部类静态方法 Outer.StaticInner.inMethod(); System.out.println("*****************************"); //创建非静态内部类实例(方式 1),并调用方法 Outer outer = new Outer(); Outer.NoStaticInner inner1 = outer.new NoStaticInner(); inner1.inFun(); //创建非静态内部类实例(方式 2) Outer.NoStaticInner inner2 = outer.getNoStaticInner(); inner1.inFun(); } } class Outer { private static String a = "外部类的静态 a"; private static String b = "外部类的静态 b"; private String c = "外部类对象的非静态 c"; private String d = "外部类对象的非静态 d"; static class StaticInner { private static String a = "静态内部类的静态 a"; private String c = "静态内部类对象的非静态 c"; public static void inMethod() { System.out.println("Inner.a = " + a); System.out.println("Outer.a = " + Outer.a); System.out.println("b = " + b); } public void inFun() { System.out.println("Inner.inFun"); System.out.println("Outer.a = " + Outer.a); System.out.println("Inner.a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); // System.out.println("d = " + d);//不能访问外部类的非静态成员 } } class NoStaticInner { private String a = "非静态内部类对象的非静态 a"; private String c = "非静态内部类对象的非静态 c"; public void inFun() { System.out.println("NoStaticInner.inFun"); System.out.println("Outer.a = " + Outer.a); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("Outer.c = " + Outer.this.c); System.out.println("c = " + c); System.out.println("d = " + d); } } public NoStaticInner getNoStaticInner() { return new NoStaticInner(); } }
8.4匿名(重要)
非匿名局部内部类语法格式
[修饰符] class 外部类{
[修饰符] 返回值类型 方法名(形参列表){
[final/abstract] class 内部类{ }
}
}
匿名内部类格式
new 父类([实参列表]){
重写方法...
}
new 父接口(){
重写方法...
}
4种匿名方式
1.提供了接口的实现类的对象
2.提供了接口的实现类的匿名对象
3.提供了接口的匿名实现类的对象
4.提供了接口的匿名实现类的匿名对象
个人理解
代码解析
public class OuterClassTest1 {
//说明:局部内部类的使用
public void method1() {
//局部内部类
class A {
//可以声明属性、方法等
}
}
//开发中的场景
public Comparable getInstance() {
//提供了实现了Comparable接口的类
//方式1:提供了接口的实现类的对象
class MyComparable implements Comparable {
//
@Override
public int compareTo(Object o) {
return 0;
}
}
MyComparable m = new MyComparable();
return m;
//方式2:提供了接口的实现类的匿名对象
class MyComparable implements Comparable {
@Override
public int compareTo(Object o) {
return 0;
}
}
return new MyComparable();
//方式3:提供了接口的匿名实现类的对象
Comparable c = new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
return c;
//方式4:提供了接口的匿名实现类的匿名对象
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}
提供了接口的实现类的对象分析
提供了接口的实现类的匿名对象分析
提供了接口的匿名实现类的对象分析
提供了接口的匿名实现类的匿名对象分析
代码分析
public class OuterClassTest2 {
public static void main(String[] args) {
SubA a = new SubA();
a.method();
//举例1:提供接口匿名实现类的对象
A a1 = new A() {
public void method() {
System.out.println("匿名实现类重写的方法method()");
}
};
a1.method();
//举例2:提供接口匿名实现类的匿名对象
new A() {
public void method() {
System.out.println("匿名实现类重写的方法method()");
}
}.method();
//举例3:
SubB s1 = new SubB();
s1.method1();
//举例4:提供了继承于抽象类的匿名子类的对象
B b = new B() {
public void method1() {
System.out.println("继承于抽象类的子类调用的方法");
}
};
b.method1();
System.out.println(b.getClass());
System.out.println(b.getClass().getSuperclass());
//举例5:
new B() {
public void method1() {
System.out.println("继承于抽象类的子类调用的方法1");
}
}.method1();
}
}
interface A {
public void method();
}
class SubA implements A {
@Override
public void method() {
System.out.println("SubA");
}
}
abstract class B {
public abstract void method1();
}
class SubB extends B {
@Override
public void method1() {
System.out.println("SubB");
}
}
class C {
public void method2() {
System.out.println("C");
}
}
提供接口匿名实现类的对象分析
提供接口匿名实现类的匿名对象分析
提供了继承于抽象类的匿名子类的对象分析
九.枚举类
9.1使用
如果针对于某个类,其实例是确定个数的。则推荐将此类声明为枚举类。
如果枚举类的实例只有一个,则可以看做是单例的实现方式。
9.2jdk5.0之前,使用自定义枚举类的方法。步骤如下:
1. 私有化类的构造器
2. 声明当前类的对象的实例变量 , 要用 final 修饰
3. 提供 get 方法
4. 创建类的实例要用 psf ( public static final )修饰,变为全局常量
//自定义枚举类 class Season{ //2.声明当前类的对象的实例变量,要用final修饰 private final String seasonName;//季节的名称 private final String seasonDesc;//季节的描述 //1.私有化类的构造器 private Season(String seasonName,String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3.提供get方法 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } //4.创建类的实例//要用psf(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{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; } }
9.3在jdk5.0时,加入使用 enum定义枚举类。步骤如下:
1. 创建对象,必须在枚举类的开头声明多个对象。对象之间使用逗号隔开。
2. 声明当前类的对象的实例变量 , 要用 final 修饰
3. 私有化类的构造器
3. 提供 get 方法格式:
【修饰符】 enum 枚举类名{
常量对象列表
}
【修饰符】 enum 枚举类名{
常量对象列表;
对象的实例变量列表;
}
要求
枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
列出的实例系统会自动添加 public static final 修饰。
如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
编译器给枚举类默认提供的是 private 的无参构造,如果枚举类需要的是无参构造, 就不需要声明,写常量对象列表时也不用加参数
如果枚举类需要的是有参构造,需要手动定义,有参构造的 private 可以省略,调用 有参构造的方法就是在常量对象名后面加(实参列表)就可以。
枚举类默认继承的是 java.lang.Enum 类,因此不能再继承其他的类型。
JDK5.0 之后 switch,提供支持枚举类型,case 后面可以写枚举常量名,无需添加枚举类作为限定。
public enum Week { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY; } public class TestEnum { public static void main(String[] args) { Season spring = Season.SPRING; System.out.println(spring); } }
//jdk5.0中使用enum关键字定义枚举类 enum Season1 { //1.创建对象,必须在枚举类的开头声明多个对象。对象之间使用逗号隔开。 Spring("春天","花开的季节"), Summer("夏天","炎热的季节"), Autumn("秋天","丰收的季节"), Winter("冬天","寒冷的季节"); //2.声明当前类的对象的实例变量,要用final修饰 private final String seasonName;//季节的名称 private final String seasonDesc;//季节的描述 //3.私有化类的构造器 private Season1(String seasonName,String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3.提供get方法 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } }
9.4Enum类中常用的方法
①使用enum定义的枚举类,默认其父类是java.lang.Enum类。(所以不能再定义其他父类)
②Enum类中的常用方法:
(如果sout输出为对象名,即默认为调用对象名.toString( )方法)
String toString( ) : 默认返回的是常量名(对象名),可以继续手动重写该方法。
String name( ) : 默认返回当前枚举对象的名称,当toString被重写了,想获得枚举类对象的名称,即用name( )
static 枚举类型[ ] values( ) : 返回枚举类型的对象数组。该方法可以很方便的遍历所有的枚举值,为静态方法。int ordinal():返回当前枚举常量的次序号,默认从0开始
9.5枚举类实现接口
情况①:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类的对象调用此方法时,执行的时是一个方法。
情况②:枚举类实现接口,在枚举类的每个对象中重写接口中的方法。操作:在对象后面加上{},在{}里面重写接口中的方法,即为在对象中重写接口中的方法。
语法:
1、枚举类可以像普通的类一样,实现接口,并且可以多个,但要求必须实现里面所有的抽象方法!
enum A implements 接口 1,接口 2{
抽象方法的实现
}
2、如果枚举类的常量可以继续重写抽象方法!
enum A implements 接口 1,接口 2{
常量名 1(参数){
抽象方法的实现或重写
},
常量名 2(参数){
抽象方法的实现或重写 },
........
}
public class SeasonTest2 { } interface Info { void show(); } enum Season2 implements Info { //1.创建对象,必须在枚举类的开头声明多个对象。对象之间使用逗号隔开。 Spring("春天","花开的季节"){ public void show() { System.out.println("春"); } }, Summer("夏天","炎热的季节"){ public void show() { System.out.println("夏"); } }, Autumn("秋天","丰收的季节"){ public void show() { System.out.println("秋"); } }, Winter("冬天","寒冷的季节"){ public void show() { System.out.println("冬"); } }; //2.声明当前类的对象的实例变量,要用final修饰 private final String seasonName;//季节的名称 private final String seasonDesc;//季节的描述 //3.私有化类的构造器 private Season2(String seasonName,String seasonDesc) { this.seasonName = seasonName; this.seasonDesc = seasonDesc; } //3.提供get方法 public String getSeasonName() { return seasonName; } public String getSeasonDesc() { return seasonDesc; } @Override public String toString() { return "Season2{" + "seasonName='" + seasonName + '\'' + ", seasonDesc='" + seasonDesc + '\'' + '}'; } }
十.包装类
10.1为什么要使用包装类?
为了使得基本数据类型的变量具备引用数据类型变量的相关特征(比如:封装性、继承性、多态性),我们给各 个基本数据 类型的变量都提供了对应的包装类。
10.2基本数据类型对应的包装类类型
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double ->Double
char -> Character
boolean -> Boolean
10.3自定义包装类
public class MyInteger {
int value;
public MyInteger() {
}
public MyInteger(int value) {
this.value = value;
}
@Override
public String toString() {
return String.valueOf(value);
}
}
10.4装箱
把基本数据类型转为包装类对象 转为包装类的对象,是为了使用专门为对象设计的 API 和特性
基本数值---->包装对象
基本数据类型 ---> 包装类:
① 使用包装类的构造器
② (建议)调用包装类的valueOf(xxx xx)
Integer obj1 = new Integer(4);//使用构造函数函数 Float f = new Float(“4.56”); Long l = new Long(“asdf”); //NumberFormatException Integer obj2 = Integer.valueOf(4);//使用包装类中的 valueOf 方法
Integer i = 4;//自动装箱。相当于 Integer i = Integer.valueOf(4);
//自动装箱: 基本数据类型 ---> 包装类 int i1 = 10; Integer ii1 = i1; //自动装箱 System.out.println(ii1.toString()); Integer ii2 = i1 + 1; //自动装箱 Boolean bb1 = true;//自动装箱 Float f1 = 12.3F; //自动装箱 //自动拆箱:包装类 ---> 基本数据类型 int i2 = ii1; //自动拆箱 boolean b1 = bb1;//自动拆箱
10.5拆箱
把包装类对象拆为基本数据类型 转为基本数据类型,一般是因为需要运算,Java 中的大多数运算符是 为基本数据类型设计的。比较、算术等
包装对象---->基本数值
包装类 ---> 基本数据类型:调用包装类的xxxValue()
包装类 ---> 基本数据类型:调用包装类的xxxValue()
Integer obj = new Integer(4); int num1 = obj.intValue();
i = i + 5;//等号右边:将 i 对象转成基本数值(自动拆箱) i.intValue() + 5; //加法运算完成后,再次装箱,把基本数值转成对象。
//推荐使用: int i2 = 10; Integer ii2 = Integer.valueOf(i2); Boolean b2 = Boolean.valueOf(true); Float f2 = Float.valueOf(12.3F);
10.6基本数据类型、包装类与字符串间的转换
常用:String类型 ---> 基本数据类型、包装类: 调用包装类的静态方法:parseXxx()
10.61基本数据类型转为字符串
方式 1:调用字符串重载的 valueOf()方法
int a = 10; //String str = a;//错误的 String str = String.valueOf(a);
方式 2:自动类型提升
int a = 10; String str = a + "";
10.62 字符串转为基本数据类型
常用:基本数据类型、包装类 ---> String类型:
① 调用String的重载的静态方法valueOf(xxx xx) ;
② 基本数据类型的变量 + ""
方式 1:使用 parseXxx 静态方法将字符串参数转换为对应的基本类型(除了 Character 类)
public static int parseInt(String s):将字符串参数转换为对应的 int 基 本类型。
public static long parseLong(String s):将字符串参数转换为对应的 long 基本类型。
public static double parseDouble(String s):将字符串参数转换为对应的 double 基本类型。
方式 2:字符串转为包装类,然后可以自动拆箱为基本数据类型
• public static Integer valueOf(String s):将字符串参数转换为对应的 Integer 包装类,然后可以自动拆箱为 int 基本类型
public static Long valueOf(String s):将字符串参数转换为对应的 Long 包装类,然后可以自动拆箱为 long 基本类型
public static Double valueOf(String s):将字符串参数转换为对应的 Double 包装类,然后可以自动拆箱为 double 基本类型
方式 3:通过包装类的构造器实现
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");
int i = new Integer(“12”);
10.7总结
十一.进制转换
11.1十进制转二进制
Integer.toBinaryString(int i)
int decimal = 10; String binary = Integer.toBinaryString(decimal); System.out.println("Binary: " + binary);
输出:
Binary: 1010
11.2十进制转八进制
Integer.toOctalString(int i)
int decimal = 10; String octal = Integer.toOctalString(decimal); System.out.println("Octal: " + octal);
输出:
Octal: 12
11.3十进制转十六进制
Integer.toHexString(int i)
int decimal = 10; String hexadecimal = Integer.toHexString(decimal); System.out.println("Hexadecimal: " + hexadecimal);
输出:
Hexadecimal: a
11.4任意进制转换
Integer.toString(int i, int radix)
方法将十进制数decimal
转换为指定进制radix
的字符串表示int decimal = 10; int radix = 5; String customRadix = Integer.toString(decimal, radix); System.out.println("Custom Radix: " + customRadix);
Custom Radix: 20
十二.大小写转化
12.1小写字母转大写字母
Character.toUpperCase(char ch)
char lowerCase = 'a'; char upperCase = Character.toUpperCase(lowerCase); System.out.println("Upper Case: " + upperCase);
输出:
Upper Case: A
12.2大写字母转小写字母
Character.toLowerCase(char ch)
char upperCase = 'A'; char lowerCase = Character.toLowerCase(upperCase); System.out.println("Lower Case: " + lowerCase);
输出:
Lower Case: a