目录
一、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
- 可以创建一个有返回值方法,然后在单元测试方法中调用并创建变量接收返回值
十、包装类
- 概念:基本数据类型可以直接使用,效率较高,但是有时我们需要将其作为引用数据类型使用,就需要包装类
- byte–Byte、short–Short、int–Integer、long–Long、float–Float、double–Double==父类是Number
- boolean–Boolean、char–Character
- 理解:将基本数据类型创建的属性外面套一个类结构,使基本数据具有引用数据类型的特点
- 为什么需要进行数据转换:
1.在某些情况下,需要使用基本数据类型对应的包装类对象,所以将起转换为包装类
2.对于包装类,我们使用的是对象,不能进行基本运算(±*/等),为了能正常运算,需要将其转为基本数据类型 - 注意:
1.装箱(基本数据类型–包装类):jdk9之后,使用构造器创建包装类对象的方法被替代了,改为使用valueOf方法
Integer integer = Integer.valueOf(33);
2.装箱(包装类–基本数据类型):使用xxxValue方法将其转换为相应类型值,在进行计算
Integer integer = Integer.valueOf(33);
int integerNum = integer.intValueOf();
3.jdk5.0之后有了自动装箱、自动拆箱特性 - 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 自动装箱
- 1.String类–基本数据类型: