this
可以用来修饰/调用属性、方法、构造器(构造方法)
修饰属性和方法:
代表的当前对象。
public class Animal{
private int age;
public void eat(){
}
public static void main(){
this.eat();
this.age = 100;
}
}
用在构造方法中:
代表当前正在创建的这个对象
调用构造器:
在类的构造器中,显示的通过this(参数/无参) 的方式调用本类中指定的其他构造器。但是具有以下两个限制:\
- this(参数/无参)在一个构造中只能使用一次(也就是说一个构造方法只能调用一个另外的构造方法)
- this(参数/无参) 必须写在构造方法的第一行。
super
父类对象的引用。一般在子类中调用父类的方法或属性时使用。一般用于当子类和父类中有同名的属性,或子类重写了父类的方法后,子类还想调用父类中的同名属性或方法时,用super显示指定。
在子类的构造器中显示的使用 super(参数/无参),表示调用父类中的有参/无参 构造器。但是这个语句必须声明在子类构造器的首行。
在子类的构造器中,如果没有显示的指定this(参数/无参)或 super(参数/无参)。那么,默认也会调用父类中的空参构造方法,也就是super()
abstract抽象类
一般,我们实例化使用一个类时,都是有意义的。比如猫啊,狗啊,都是具体的。但很少去实例化没具体意义的类,比如动物类、人类。虽然语法上没问题,但却没有现实意义。这种类更多的是等着被继承的父类形式存在。一般我们将其声明为抽象类
abstract
public abstract class Animal{
}
抽象类虽然不能实例化,但抽象类依然具有构造器(别忘了子类实例化时要调用哦):默认自带无参构造器,也可以定义带参构造器。
抽象方法
与抽象类意思一样,抽象方法不用具体实现,只是告诉子类具有哪些行为能力,具体实现根据子类的不同再各自定义。这样的方法,成为抽象方法。
public abstract void 方法名(参数 );
//不能有方法体
-
子类必须重写实现父类的抽象方法,除非子类也是抽象类
-
抽象类里可以没有抽象方法,但抽象方法必须存在于抽象类中
( 抽象类=》抽象非抽象方法,抽象方法=》抽象类 )
- 抽象类有一个比较成功的应用,就是模板设计模式。
在设计模式章节会介绍
static
当我们编写一个类的时候,其实就是在描述其对象的属性和行为。而并没有产生实质上的对象。只有通过new关键字才会产生对象。这时系统才会分配内存空间给对象。其方法才可以供外部调用。我们有时希望,无论是否产生对象,或者无论产生多少对象。某些特定的数据在内存里都有且只有一份。这就需要static关键字了。
static修饰的成员变量
成为静态成员变量/类成员变量。无论该类实例出多少对象,这些对象中的静态成员变量共用一块内存空间(存在方法区中)。
只有当所有对象都销毁后,这块空间才会被释放(严格的说,应该是方法区中的类被释放后,才会被释放)
静态成员变量又称为类成员变量,它随着类的加载而加载,不属于具体的某一对象,可以直接用类名调用。由于类只加载一次(Class加载到方法区),所以,静态变量在内存中也只存在一份。
实例对象也可以调用静态属性
static修饰代码块(用{}括起来的一段代码,也叫初始化块)
称之为静态代码块
静态代码块执行顺序 优先于 构造代码块
当类被实例化多次时:
构造代码块执行多次,静态代码块只执行一次
静态代码块中同样不允许访问普通类成员
(为啥?因为静态的代码 加载时,普通成员还不一定有呢,它要随着对象的的创建而创建)
开发中,如何确定一个方法或属性是否要声明为static:
- 属性时可以被多个对象所共享的,通常声明为static
- 操作静态属性的方法,通常声明为static方法(不然还要实例一个对象调用这个方法去操作本可以直接用类访问的静态属性,这不脱离裤子...)
- 工具类中的方法,通常声明为static方法
static修饰的属性存放在方法区的静态域中
package com.hellomeng.oop.statics;
public class StaticTest {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
System.out.println("c1.id="+c1.getId()+" "+"当前共"+Circle.getTotal()+"个");
//c1.id=1001 当前共2个
System.out.println("c2.id="+c2.getId()+" "+"当前共"+Circle.getTotal()+"个");
//c2.id=1002 当前共2个
}
}
class Circle{
private Double radius;
private Integer id;
private static Integer total = 0; //一共造了多少个圆
private static Integer init = 1001; //当前圆的编号到哪里了,后面的圆从这里开始编号
public Circle(){
id = init++;
total = total + 1;
}
public Double getRadius() {
return radius;
}
public void setRadius(Double radius) {
this.radius = radius;
}
public Integer getId() {
return id;
}
public static Integer getTotal() {
return total;
}
}
为啥是2个。因为当第一行 System.out.println开始输出的时候。total已经累计到2了?为啥会累计,因为是static的。
final-最终的
final修饰的类,类不能被继承,可以理解为最终的类,断子绝孙类,不可能有孩子的,有也是别人的😏。
public final class 类名{
//这个类不能被继承
}
final修饰方法,方法不能被重写
public final void 方法名(参数){
//此方法不能被重写,但子类依然可以使用此方法
}
final修饰方法内的局部变量-只能赋值一次。
final int sum = 0;//只能赋值一次
下面这样也可以
final int sum;
sum = 0;//使用前初始化一次
final修饰成员变量 - 声明时直接初始化,或者在构造方法或构造代码块中赋值,其他地方不可以赋值
public final int age = 0;
public final int age;//如果这里没赋值,那么只能在构造代码块或构造方法中为其赋值
⚠️:通过final 和 static共同修饰的,表示全局不允许被修改的内容。一般修饰配置信息等内容