三个关键字
abstract/static/final
一.抽象
1.什么是抽象
似是而非的,像却又不是;具备某种对象的特征,但不完整。
二.抽象类、抽象方法*
2.1抽象类
1.不能被实例化的类,需要加abstract修饰,叫做抽象类。
2.2抽象类的作用
1.充当子类的模板,可被子类继承提供共性的属性和方法
2.可声明为引用,更自然的使用多态
2.3抽象方法
1.抽象类中,有相关行为,无法具体实现,需加abstract修饰,叫做抽象方法,
2.抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
代码块:
创建抽象类动物,使用子类继承,运行测试方法 (Animal,Dog,Cat和Test类)
public abstract class Animal { //抽象类
public Animal() {}
//抽象方法
public abstract void bark();
//非抽象方法
public void eat() {}
}
//子类继承父类后(父类有bark的抽象方法),报错了
//方案1,子类需要重写父类的方法(Dog)
//方案2. 将自身变为抽象,这样,可以交给自己的子类去完成
class Dog extends Animal{
@Override
public void bark() {
System.out.println("汪汪汪~~~叫");
}
}
abstract class Cat extends Animal{
}
class Text{
public static void main(String[] args) {
//Cannot instantiate the type Animal
// Animal a=new Animal();
//被abstract修饰的类,抽象类不能实例化对象
Animal animal = new Dog(); //多态用法
animal.bark();
}
}
三.静态属性
3.1实例属性
实例属性:是每个对象各自持有的独立空间(多份),对象单方面修改,不会影响其他对象。
通过代码理解
class GirlFrend {
int age; //成员属性
}
public class Test {
public static void main(String[] args) {
GirlFrend fengjie = new GirlFrend();
fengjie.age = 20;
GirlFrend liuyifei = new GirlFrend();
liuyifei.age = 30;
//实例化的两个对象,每个对象都拥有独立的成员属性
System.out.println(fengjie.age); //20
System.out.println(liuyifei.age); //30
}
}
3.2静态属性
静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
通过代码理解
//static: 属于类,在类加载的时候进行加载,优先于对象, 每一个对象共享同一份静态属性
class GirlFrend2 {
static int age; //静态属性
}
public class Test2 {
public static void main(String[] args) {
GirlFrend2 fengjie = new GirlFrend2();
fengjie.age = 20;
GirlFrend2 liuyifei = new GirlFrend2();
//The static field GirlFrend2.age should be accessed in a static way
liuyifei.age = 30; //应该通过类名来调静态属性: GirlFrend2.age
//实例化的两个对象,每个对象都拥有独立的成员属性
System.out.println(fengjie.age); //30
System.out.println(liuyifei.age); //30
}
}
3.3什么是静态
概念:
- 静态(static)可以修饰属性和方法。
- 称为静态属性(类属性)、静态方法(类方法)。
- 静态成员是全类所有对象共享的成员。
- 在全类中只有一份,不因创建多个对象而产生多份。
- 不必创建对象,可直接通过类名访问
案例
统计一个类的对象被创建了多少次
class MyClass{
static int count; //统计创建次数
public MyClass() {
count++;
}
}
public class Test3 {
public static void main(String[] args) {
new MyClass();
new MyClass();
new MyClass();
//每个对象只有同一份共享的静态属性
System.out.println(MyClass.count);
}
}
四.静态方法
4.1静态方法
代码块:
//静态方法:调用方式,通过类名去调用; 如果在本类中可以省略类名
//应用场景: 用作工具类使用--在其他项目中也可以共享方法的实现
public class Test {
public static void main(String[] args) {
int sum = MyTool.add(1,2); // 在本类中调用静态方法,可以省略类名
System.out.println(sum);
//在实际应用中:
int[] a = {9,5,2,7};
System.out.println("排序前:"+Arrays.toString(a));
//Arrays.sort(a); //系统已经写好了静态方法的具体实现
MyTool.sort(a); //自定义静态方法
System.out.println("排序后:"+Arrays.toString(a));
}
}
4.2静态的特点
1.静态方法允许直接访问静态成员
2.静态方法不能直接访问非静态成员
3.静态方法中不允许使用this或super关键字
4.静态方法可以继承,不能重写,没有多态
代码块:
class MyClass{
static int a; //静态属性
int b; //成员属性
public void test() {
System.out.println(a); //成员方法中可以使用静态属性
}
public static void test2() {
System.out.println(a); //在静态方法中可以使用静态属性
//Cannot make a static reference to the non-static field b
//System.out.println(b); //在静态方法中不能使用非静态属性--加载时机问题
// System.out.println(this); //静态方法不能使用this--加载时机
}
}
class MyA extends MyClass{
//@Override
//public static void test2() {} //静态方法不能重写
}
public class Test2 {
public static void main(String[] args) {
new MyA().test2(); //静态方法具有继承性
}
}
4.3动态和静态代码块
静态代码块只执行一次,动态代码块随着实例化的次数而执行。
//代码块: 分为动态代码块和静态代码块
class MyClass{
static int a = 3;
String field = "成员属性";
public MyClass(){
System.out.println("构造方法");
}
{
System.out.println(field);
System.out.println("动态代码块");
}
public static void test() {
System.out.println("调静态方法...");
}
}
class MySon extends MyClass{
}
public class Test {
public static void main(String[] args){
new MyClass(); //实例化自身
System.out.println("=======>");
new MyClass(); //实例化两次,则会触发两次动态代码块
//new MySon();
//System.out.println(MyClass.a);
//MyClass.test(); //调静态方法
}
}
五.final
5.1final
概念:最后的,不可更改的。
- final可修饰的内容:
- 类(最终类)
- 方法(最终方法)
- 变量(最终变量)
final和static绝配
5.2final类
final修饰类:此类不能被继承。
String、Math、System均为final修饰的类,不能被继承。
final修饰方法:此方法不能被覆盖。
意为最终方法,不支持子类以覆盖的形式修改。
5.3 final变量
final修饰变量:此变量值不能被改变(常量)。
5.4final修饰成员变量,局部变量
final修饰成员变量
- 实例常量赋值时机:显示初始化,动态代码块,构造方法
- 静态常量赋值时机: 显示初始化和静态代码块
final修饰局部变量
- 基本类型变量: 该变量值不能被改变
- 引用类型变量: 地址不可改变
5.5案例
/*final*/ class MyClass{
//The blank final field a may not have been initialized
final String a; //final修饰属性,必须要初始化值
//final成员变量赋值方式: 1. 初始化 2. 动态代码块 3. 构造方法
// {
// a = "999";
// }
public MyClass() {
a = "555";
}
//final静态变量赋值方式: 1. 初始化 2. 静态代码块
final static int b;
static {
b = 9;
}
public /*final*/ void test() {
}
int e;
}
//The type MySon cannot subclass the final class MyClass
class MySon extends MyClass{//MyClass不能有子类
@Override
public void test() { //Cannot override the final method from MyClass
}
}
public class Test {
public static void main(String[] args) {
//注意: final修饰的变量,都变为了常量
final int c = 6; //修饰基本变量
//c = 9;
//MyClass.b = 999;
//------------final修饰引用对象的特点:地址不能改变,但值可以改变------------------
final int[] d = {1,3,5}; //不能改变数组引用对象
//d = new int[] {2,4};
d[0] = 6; //里面的内容可以改
final MyClass class1 = new MyClass();
//class1 = new MyClass();
class1.e = 8;
}
}
//静态常量的应用场景: 作为状态值使用(就是用于做判断) static+final(绝配)
//写法: 静态常量,往往都是大写,如果有多个单词,则用_拼接
//好处: 可读性强, 可维护性强
class MyValue{
static final int SEX_MAN = 1;
static final int SEX_WOMAN = 2;
}
public class Test2 {
public static void main(String[] args) {
int value = MyValue.SEX_MAN;
switch (value) {
case MyValue.SEX_MAN:
System.out.println("男人");
break;
case MyValue.SEX_WOMAN:
System.out.println("女人");
break;
default:
break;
}
}
}