static-final-abstract-单例设计模式
static修饰符
static简介
static概述
static是静态修饰符,一般修饰成员。被static所修饰的成员属于整个类,而不是属于某个具体的对象,该类的所有实例化对象共有该成员。被static修饰的成员又叫类成员,不叫对象的成员。
案例
/**
* @ClassName: Chinese
* @Description: Chinese中国人类
*
* 中国人类
* 国籍,姓名,年龄,职业
* 其中,国籍应该被共享
* 姓名,年龄,职业各个对象有各个对象的值
*
*/
public class Chinese {
public static String country = "中国";
private String name;
private int age;
private String work;
public Chinese() {super();}
public Chinese(String name, int age, String work) {
super();
this.name = name;
this.age = age;
this.work = work;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public String getWork() {return work;}
public void setWork(String work) {this.work = work;}
}
public class StaticDemo {
public static void main(String[] args) {
//创建人类对象,验证静态static修饰的成员被多个对象共享
Chinese c = new Chinese("王宝强", 34, "演员");
System.out.println(c.getAge()+"岁的"+c.getName()+"是"+c.country+"人");
Chinese c2 = new Chinese("周星驰", 48, "演员或导演或制片");
System.out.println(c2.getAge()+"岁的"+c2.getName()+"是"+c2.country+"人");
c.country = "中华人名共和国";
System.out.println("================================");
System.out.println(c.getAge()+"岁的"+c.getName()+"是"+c.country+"人");
System.out.println(c2.getAge()+"岁的"+c2.getName()+"是"+c2.country+"人");
}
}
static的使用方式及加载原理
概述
被static修饰的成员可以通过类名直接访问,也可以通过实例化一个对象,在通过对象来调用。
格式:
类名.静态成员变量名
类名.静态成员方法名(参数列表)
对象名.静态成员变量名
对象名.静态成员方法名(参数列表)
最后两种不推荐
案例
package com.feng;
/**
* @Description TODO
* @Author Cautious-Xin
* @Date 2020/10/31 8:29
*/
public class Animal {
private static String name = "老虎";
public Animal(String kind) {
this.kind = kind;
}
public Animal() {
}
private String kind;
public static void run(){
System.out.println("这是静态的奔跑方法");
}
public void hunting(){
System.out.println("这是普通的成员捕猎方法");
}
public static void main(String[] args) {
Animal a = new Animal("东北虎");
System.out.println(Animal.name);
//System.out.println(Animal.kind);//编译报错,因为kind不是静态修饰的,不可以直接通过类名使用
Animal.run();
//Animal.hunting();//编译报错,因为hunting不是静态方法
a.hunting();
a.run();//静态方法可以被具体的对象调用
}
}
加载原理
以上述代码为例,Animal类的.class文件会率先被加载进方法区中,在方法区中存在着一款静态区,这是属于Animal类的静态区,Animal类中被static修饰的成员均存在于这里,不推荐使用对象名进行调用的原因:
使用场景
1、编写工具类的时候,其中的方法多为静态方法
2、所有对象需要共享某个属性的时候
注意事项
1.实例方法中可不可以访问实例成员变量? 可以
2.实例方法中可不可以访问实例方法? 可以
3.实例方法中可不可以访问静态成员变量? 可以
4.实例方法中可不可以访问静态方法? 可以
5.静态方法中可不可以访问静态成员变量? 可以
6.静态方法中可不可以访问静态方法? 可以
7.静态方法中可不可以访问实例成员变量? 不可以
8.静态方法中可不可以访问实例方法? 不可以
静态方法不可以访问实例成员方法和成员变量的原因是,静态方法是随着类的加载而加载进内存,不需要创建类的具体对象就会存在于内存中,而成员变量和成员方法需要创建对象之后才会存在。被static修饰的成员和方法只会加载一次
final关键字
概述
final:表示不可改变,最终的含义。可以用于修饰类,方法,变量。
1、final修饰类,代表当前类不在可以被继承
2、final修饰方法,代表当前方法不允许被重写
3、final修饰变量,代表变量的值不可更改(若是基本数据类型,数值(二进制值)不可以更改,若是引用数据类型,地址不可以在更改)
使用方式
修饰类
格式
final class 类名 {
}
案例
public final class Animal {
private String name;
}
//class Tiger extends Animal{
//Cannot inherit from final 'com.feng.finaltest.Animal'
//}
//由于Animal被final修饰,所以不可以在被其他的类继承
修饰方法
格式
修饰符 final 返回值类型 方法名(参数列表){
//方法体
}
案例
public class Animal {
private String name;
public Animal(String name) { this.name = name; }
public final void run(){}
public final void run(String name){}
}
class Tiger extends Animal{
public Tiger(String name) { super(name); }
/*@Override
public void run(){
//'run()' cannot override 'run()' in 'com.feng.finaltest.Animal'; overridden method is final
}*/
//Cannot inherit from final 'com.feng.finaltest.Animal'
}
/**
* final修饰的方法不支持重写,但是可以重载
* final不可以修饰构造方法
*/
修饰局部变量
局部变量—基本数据类型
//修饰方法体中的参数
public class Test {
public void run(){
final int a = 0;
// a = 20;出现错误,以为a被final修饰,只能进行一次赋值
final int b;
b = 20;
//b = 22;出现错误,以为b被final修饰,只能进行一次赋值
}
}
//修饰形式参数
public class Test {
public void run(final int a){
// a = 20;//报错,a是被final修饰的形式参数,不允许被二次赋值,只允许调用
System.out.println(a);
}
}
局部变量—引用数据类型
public class Test {
public void run(final int a){
final Animal animal = new Animal("");
//animal = new Animal("");animal被final修饰,不可以重新赋值,改变其地址
//animal = null;
}
public void eat(final Animal a){
//a = new Animal("");//Cannot assign a value to final variable 'a'
}
}
修饰成员变量
实例成员变量
public class Animal {
final int age;//final 修饰,所以必须再定义
// 的时候赋初值或者在每个构造方法中赋值
final int num = 10;
public Animal(int age) {
this.age = age;
}
public Animal() {
this.age = 10;
}
}
总结
final 修饰变量,代表变量的值不可更改
实例成员变量(属性)
1.一旦使用final修饰后,需要先进行初始化赋值
2.若不赋初始值,则必须在所有的构造方法中赋值
3.若不赋初始值,实例代码块 ???是否必须赋值
静态成员变量(static) 在内存中地址唯一,值唯一不可更改
1.final修饰之后,静态的常量,需要先进行初始化赋值
2.public static final 变量名全部大写,多个单词之间用_拼接
3.若不赋初始值,静态代码块 ???是否必须赋值
局部变量(方法中声明的变量)
1.一旦被final修饰,值不可以更改
2.方法中形参被final修饰,此方法不可以再更改形参的值
(一般是让值被固定或者保护起来,执行的过程中防止被修改)
提问:
final与 abstract 能否一起使用??? 不可以一起使用
抽象类和抽象方法
抽象类的概述
抽象类是用来描述一种类型应该具备的基本特征与功能,具体如何去完成这些行为由子类通过方法重写来完成。
我们把没有方法体的方法称为抽象方法,java语法规定含有抽象方法的类就时抽象类。
抽象类的定义格式
public abstract class 类名 {}
public abstract class Employee {
//抽象方法:需要abstract修饰,并分号;结束
// 抽象工作方法
public abstract void work();
}
public class Waiter extends Employee {
/*
* 重写了父类的抽象方法,加入了方法体,描述出具体逻辑
*/
//服务员的工作类
@Override
public void work() {
System.out.println("等着顾客叫餐!");
}
}
抽象类的构造方法
构造方法存在的意义
子类继承抽象的父类,在创建子类对象的时候需要调用父类的构造方法然后为抽象类中的成员变量赋值,赋值好的父类成员变量就可以被子类的对象使用。
抽象类的特点及注意事项
特点
A:抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
B:抽象类不可以直接创建对象,原因:调用抽象方法没有意义。
C:只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。
之所以继承抽象类,更多的是在思想,是面对共性类型操作会更简单。
注意事项
-
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
-
抽象类中,可以有构造器,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
-
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
-
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
-
抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想。
理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。
抽象类存在的意义
抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义,抽象类体现的是模板思想,模板是通用的东西抽象类中已经是具体的实现(抽象类中可以有成员变量和实现方法),而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求,这是典型的模板思想。
单例设计模式
作用
单例模式,是一种常用的设计模式。同过单例模式可以保证系统中,应用该模式的这个类只有一个实例。即一个类只有一个对象市里
实现步骤
1、将构造方法私有化,使其不能够在类外通过new来调用构造方法进行实例化对象
2、在该类的内部产生一个唯一的实例化对象,并且将其封装为private static 类型的成员变量
3、定义一个静态方法返回这个唯一的对象
单例模式的类型
1、饿汉单例设计模式
2、懒汉单例设计模式
3、静态内部类的单例设计模式
4、线程安全的单例设计模式
饿汉单例设计模式
饿汉单例设计模式就是使用类的时候已经将对象创建完毕,不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故被称为“饿汉模式”。
public class Singleton {
// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
private Singleton() {}
// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
private static final Singleton instance = new Singleton();
// 3.定义一个静态方法返回这个唯一对象。
public static Singleton getInstance() {
return instance;
}
}
懒汉单例设计模式
懒汉单例设计模式就是调用getInstance()方法时实例才被创建,先不急着实例化出对象,等要用的时候才例化出对象。不着急,故称为“懒汉模式”。
public class Singleton {
// 2.在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
private static Singleton instance;
// 1.将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
private Singleton() {}
// 3.定义一个静态方法返回这个唯一对象。要用的时候才例化出对象
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
注意:懒汉单例设计模式在多线程环境下可能会实例化出多个对象,不能保证单例的状态。