JavaSE-修饰符、关键字
this
this关键字:出现在成员方法、构造器中代表当前对象的地址,用于访问当前对象的成员变量、成员方法
- this出现在构造器中,可以引用该构造器正在初始化的对象
- this出现在成员方法中:可以引用调用该方法的对象
- 在构造器的最起始处,可以使用this()调用其他的构造器,并且不能调用两个,否则编译器会报错
super
当子类重写覆盖了父类成员后,子类的对象将无法访问父类中被覆盖的成员,但可以在子类方法中使用 super 关键字调用父类中被覆盖的成员
语法格式:super.父类成员变量/父类成员方法
子类不会获得父类的构造器,但是子类构造器里可以使用 super 来调用父类构造器的初始化代码。且使用 super 调用父类构造器也必须出现在子类构造器执行体的第一行,所以 this 调用和 super 调用不会同时出现
不管是否使用 super 调用来执行父类构造器的初始化代码,子类构造器总会调用父类构造器一次。子类构造器调用父类构造器分为如下几种情况:
- 子类构造器执行体的第一行使用 super 显示调用父类构造器,系统将根据 super 调用里传入的实参列表调用父类对应的构造器
- 子类构造器执行体的第一行使用 this 显示调用本类中重载的构造器,系统将根据 this 调用里传入的实参列表调用本类中的另一个构造器。执行本类中另一个构造器时即会调用父类构造器
- 子类构造器执行体中既没有 super 调用,也没有 this 调用,系统将会在执行子类构造器之前,隐式调用父类无参数的构造器(也就是子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己)
点击查看代码
class SuperClass {
public int num1;
public SuperClass() {
}
public SuperClass(int num1) {
this.num1 = num1;
}
public void test() {
System.out.println("hello SuperClass!");
}
}
public class SubClass extends SuperClass {
public int num2;
public SubClass(int num1, int num2) {
super(num1);
this.num2 = num2;
}
@Override
public void test() {
System.out.println("hello SubClass!");
}
public void testSuper() {
// output: 66
System.out.println(super.num1);
// output: hello SuperClass!
super.test();
}
public static void main(String[] args) {
new SubClass().testSuper();
}
}
总结 this 和 super:this代表本类对象的引用;super代表父类存储空间的表示
| 关键字 | 访问成员变量 | 访问成员方法 | 访问构造方法 |
|---|---|---|---|
| this | this.成员变量 (访问本类成员变量) |
this.成员方法(…) (访问本类成员方法) |
this(…) (访问本类构造器) |
| super | super.成员变量 (访问父类成员变量) |
super.成员方法(…) (访问父类成员方法) |
super(…) (访问父类构造器) |
static
static是静态的意思,可以修饰成员变量和成员方法
- static修饰成员变量表示该成员变量只在内存中只存储一份(属于类,在内存中只加载一次),可以被共享访问、修改
- 类名.静态成员变量(推荐)
- 对象.静态成员变量(不推荐)
- static修饰方法表示该方法属于类;静态方法是没有this参数的方法。在static方法的内部不能调用非静态方法,因为它不能操作对象。普通成员方法可以访问静态方法
- 类名.静态成员方法(推荐)
- 对象.静态成员方法(不推荐)
- 注意:静态方法中是不可以出现this关键字的
final
final 关键字可用于修饰类、变量和方法,表示它修饰的类、变量和方法不可改变
final修饰变量时,表示该变量一旦获得了初始值就不可被重新赋值,final既可以修饰成员变量(包括实例变量和类变量),也可以修饰局部变量、形参
- final修饰的类表示该类是最终类,不能被继承、没有子类
- final修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用final修饰该方法
- final修饰的变量必须显示地指定初始值,系统不会对final修饰的变量进行隐式初始化
- final修饰的变量是基本数据类型:那么变量存储的数据值不能发生改变
- final修饰的变量是引用数据类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的
abstract
抽象类和抽象方法必须使用 abstract 修饰符来定义
抽象类语法格式:修饰符 abstract class 类
抽象方法语法格式:修饰符 abstract 返回值类型 方法名称(形参列表);
- 抽象类必须使用 abstract 修饰符来修饰,抽象方法也必须使用 abstract 修饰符来修饰,抽象方法不能有方法体
- 抽象类不能被实例化,无法使用 new 关键字来调用抽象类的构造器创建抽象类的实例。即使抽象类里不包含抽象方法,这个抽象类也不能创建实例
- 抽象类可以包含成员变量、方法、构造器、初始化块、内部类。抽象类的构造器不能用于创建实例,主要是用于被其子类调用
- 抽象类里可以没有抽象方法,但有抽象方法的类只能被定义为抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
- 不能用abstract修饰变量、代码块、构造器
final 和 abstract 是互斥关系:使用abstract修饰方法表明这个方法必须由子类重写;而final 修饰的类不能被继承,final修饰的方法不能被重写。因此 final 和 abstract 永远不能同时使用
static 和 abstract:它们之间不能同时修饰某个方法,但它们可以同时修饰内部类
private 和 abstract:abstract 方法不能定义为 private 访问权限,即 private 和 abstract 不能同时修饰方法
enum
在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有四个对象,这种实例有限而且固定的类,在Java中被称为枚举类。枚举类是一个特殊的类,它一样可以有自己的成员变量、方法,可以实现一个或多个接口,也可以定义自己的构造器
枚举类的语法格式:修饰符 enum 枚举名称{}
枚举的作用:"是为了做信息的标志和信息的分类"
枚举的特征
- 使用 enum 定义的枚举类默认继承了
java.lang.Enum类,而不是默认继承了Object类,因此枚举类不能显示继承其他父类 - 使用 enum 定义的、非抽象的枚举类默认会使用 final 修饰表示最终类,因此枚举类不能派生子类,不能被继承
- 枚举类的构造器只能使用 private 修饰符,如果省略了构造器的修饰符,则默认会使用 private。由于构造器都是私有的,所以枚举对外不能创建对象
- 枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加
public static final修饰,无需手动添加 - 枚举类默认有一个 values() 方法,返回该枚举类的所有实例
- 枚举类相当于是多例模式
反编译后观察枚举的特征
// java源代码
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
// 反编译的代码:Compiled from "Season.java"
public final class Season extends java.lang.Enum {
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();
public static Season[] values();
public static Season valueOf(java.lang.String);
}
// 枚举类的 switch 用法
public class EnumTest {
public void judge(Season s) {
switch (s) {
case SPRING:
System.out.println("spring");
break;
case SUMMER:
System.out.println("summer");
break;
case AUTUMN:
System.out.println("autumn");
break;
case WINTER:
System.out.println("winter");
break;
}
}
}
package、import、import static
package:Java引入了包机制,提供了类的多层命名空间,用于解决类的重名冲突、类文件管理等问题
Java允许将一组功能相关的类放在同一个 package 下,从而组成逻辑上的类库单元
package 语法结构:package packageName;
- package 语句必须作为源文件的第一条非注释性语句,一个源文件只能指定一个包,即只能包含一条 package 语句
- 如果没有显示指定 package 语句,则处于默认包下(default package)默认包是一个没有名字的包
- 同一个包下的类可以自由访问
- 父包和子包在用法上不存在任何关系,如果父包中的类需要使用子包中的类,则必须使用子包的全名,而不能省略父包部分
import:如果创建处于其他包下类的实例,则在调用构造器时也需要使用包前缀。为了简化编程,Java引入了 import 关键字,import 可以向某个Java文件中导入指定包层次下某个类或全部类(包名建议全部英文小写,且具备意义)
import 语法结构:import package.subpackage……ClassName
- import 语句应该出现在 package 语句之后、类定义之前,且可以包含多个 import 语句
- import 语句还可以使用通配符(*)表示导入指定包下的全部类,注意通配符只能代表类,不能代表包,所以指定包下的子包内的类不会被导入
- 一旦在Java源文件中使用 import 语句来导入指定类,在该源文件中使用这些类时就可以省略包前缀,不再需要使用类全名
- Java默认为所有源文件导入
java.lang包下的所有类,因此在Java程序中使用 String、System类时都无须使用 import 来导入这些类
import static:JDK1.5 新增了一种静态导入的语法,用于导入指定类的某个静态成员变量、方法或全部的静态成员变量、方法。在使用 import static 时,可以省略类名
静态导入使用 import static 语法;静态导入的两种语法:
- 导入指定类的全部静态成员变量、方法:
import static package.subpackage……ClassName.*; - 导入指定类的单个静态成员变量、方法:
import static package.subpackage……ClassName.fieldName|methodName;
点击查看代码
// 方式一:完整包名
java.time.LocalDate today = java.time.LocalDate.now();
// 方式二:import 语句
import java.time.LocalDate;
// 同时导入了多个类,无法判断具体类时
import java.util.*;
import java.sql.*;
java.util.Date deadline = new java.util.Date();
java.sql.Date tody = new java.sql.Date(…);
// import 语句导入静态方法和静态域功能
import static java.lang.System.*;
out.println("hello world");