本文介绍六个关键字:static、final、extends、implements、this、super,下面具体介绍各个关键字及需要注意的点。
记住1:两个保留字:const和goto (保留字:现在没用,以后用得上)
记住2:所有的关键字都是小写,一旦有大写的,一定不是关键字
static是java中的一个关键字(key words),其表示的含义在于被static修饰的域、方法、代码块为类所有,而不是为代码所有,使用类名调用(亦可使用对象名调用),static域加载时仅加载一次。
第一点,非static方法、代码块内可以有非static域、方法、代码块,也可以有static域、方法、代码块;但是static方法、代码块内可以只能出现static域、方法、代码块,即static域、方法、代码块仅出现在static环境(static方法、代码块)下,static域只能出现在static方法或代码块中,static方法只能在static方法或代码块中被调用。如图1所示。
图1 外层环境与内部变量之间的关系
第二点,static方法可以用类名调用,也可以用对象名调用,但是非static方法只能由对象名调用调用,因为非static方法只有在对象存在时才有意义,如图2所示。
图2 static方法和非static方法调用方式
・定义格式:
static 数据类型 变量名;
当 static 修饰成员方法时,该方法称为类方法 。静态方法在声明中有 static ,建议使用类名来调用,而不需要创建类的对象。调用方式非常简单。类方法:使用 static 关键字修饰的成员方法,习惯称为静态方法。
・定义格式:
修饰符 static 返回值类型 方法名 (参数列表){// 执行语句}
・静态方法调用的注意事项:
1. 静态方法可以直接访问类变量和静态方法。(静态方法只能访问静态成员。)
2. 静态方法不能直接访问普通成员变量或成员方法。反之,成员方法可以直接访问类变量或静态方法。
3. 静态方法中,不能使用 this 关键字。
public class MyClass {
int num; // 成员变量
static int numStatic; // 静态变量
// 成员方法
public void method() {
System.out.println("这是一个成员方法。");
// 成员方法可以访问成员变量
System.out.println(num);
// 成员方法可以访问静态变量
System.out.println(numStatic);
}
// 静态方法
public static void methodStatic() {
System.out.println("这是一个静态方法。");
// 静态方法可以访问静态变量
System.out.println(numStatic);
// 静态不能直接访问非静态
// System.out.println(num); // 错误写法!
// 静态方法中不能使用this关键字。
// System.out.println(this); // 错误写法!
}
}
・调用格式
被 static 修饰的成员可以并且建议通过类名直接访问。虽然也可以通过对象名访问静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员,但是不建议,会出现警告信息。
格式:// 访问类变量类名.类变量名;// 调用静态方法类名.静态方法名(参数);
静态原理图解
static 修饰的内容是随着类的加载而加载的,且只加载一次。
存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。
它优先于对象存在,所以,可以被所有对象共享。
public class ClassName{static {// 执行语句}}
作用:给类变量进行初始化赋值。
Java语言中final是一个关键字(key words),其表示的三个含义:final修饰的变量是常量,final修饰的类不可继承,final修饰的方法不可重写。
final关键字三个特性:final修饰的变量为常量、final修饰的类不可继承、final修饰的方法不可重写。
对于final修饰的变量,应该对基本类型和引用类型分开讨论:
基本类型为栈内存(-128~127情况下),一旦被final关键字修饰,其变量属性变为只读,不再进行写操作,否则编译报错。
引用类型为堆内存,一旦被final关键字修饰,则引用不再改变,但是引用所指向的对象是可以被修改的,Java语言并未提供任何方式使用对象恒定不变。示意代码如下:
public class FinalData {
private final Value value=new Value(22);
public static void main(String[] args) {
FinalData finalData=new FinalData();
//finalData.value=new Value(33); //编译报错 value为final类型
finalData.value.i++; // 编译通过 value所指向的对象可以修改
}
}
class Value{
int i;
public Value(int i){
this.i=i;
}
}
final变量定义时初始化常见,定义时直接赋值即可,不再赘言。
因为被final修饰的变量一定要在使用前被初始化,所以如果没在定义操作,一定在构造函数中初始化,这种情况称为空白final。示例代码如下:
public class FinalData {
private final int i;//基本类型示意
private final Value value;//引用类型示意
public FinalData(){ // 无参构造函数 空白final
i=1;
value=new Value(1);
}
public FinalData(int x){//有参构造函数 空白final
i=x;
value=new Value(x);
}
public static void main(String[] args) {
new FinalData();
new FinalData(22);
}
}
class Value{
int i;
public Value(int i){
this.i=i;
}
}
类使用final关键字修饰之后,该类不可被继承,可以起到保护该类的作用。实例代码如下:
final class FinalFatherClass{
}
class SonClass extends FinalFatherClass{ //编译报错 final类不允许继承
}
class FinalFatherClass{
final void f(){
System.out.println("FinalFatherClass f()");
}
}
class SonClass extends FinalFatherClass{
final void f(){//编译报错
// 子类中某一方法的方法签名(方法名+形参列表)与父类相同,即可认为子类中该方法重写父类方法
//因final方法不可被重写,顾此处编译报错
System.out.println("SonClass f()");
}
}
值得注意的是,子类虽不能重写父类final函数,但是可以继承父类final函数,示意代码如下:
public class TestFinal {
public static void main(String[] args){
FinalFatherClass son=new SonClass();
son.f(); //打印 FinalFatherClass f()
//因为子类未重写父类final函数,也不能重新父类final函数
//但子类可以继承父类final函数,所以调用父类 f() 打印 FinalFatherClass f()
}
}
class FinalFatherClass{
final void f(){
System.out.println("FinalFatherClass f()");
}
}
class SonClass extends FinalFatherClass{
}
从上面可以看到,final修饰的方法在特定的访问权限下可以被继承。
这是因为,方法是否被final修饰与方法的访问权限是两回事,没有任何关系,被final修饰的方法和未被final修饰的方法都可以自由的指定访问权限。
我们有兴趣去谈论final关键字和访问权限关键字在修饰方法的过程的起到的作用, 如下表(声明:final和访问权限是两个独立的概念,没有任何比较意义,所有本表仅方便读者理解,不可作为正统知识) :
小结 private<final<protect (仅适用于方法)
从表中可以看到,protect修饰的方法在子类中可见,所有可以被子类继承,亦可以被子类重写;
final修饰的方法可以被子类继承,但不可被子类重写(这里final方法的访问权限为默认的default、protected、public均可,只要保证子类可见即可);
private修饰的方法由于仅本类可见,故不能被子类继承,亦不能被子类重写。
实际上,Java语言中,所有被private关键字修饰的方法都隐式的被final关键字修饰,(正如上表所示,private实现了final方法不可重写的功能,并附加不可继承功能。)(再次声明:final和访问权限是两个独立的概念,没有任何比较意义,所有上表仅方便读者理解,不可作为正统知识)可以对private方法添加final关键字,但是这种做法没有任何意义。代码示例如下:
public class TestFinal {
public static void main(String[] args){
FinalFatherClass fatherClass=new FinalFatherClass();
SonClass sonClass=new SonClass();
//fatherClass.f(); //f() 为final方法 被private修饰后 仅本类可见 所有不能到TestFinal类中调用
//sonClass.f();
//fatherClass.g(); //g() 虽然不是final方法 但被private修饰后 也是仅本类可见 所有不能到TestFinal类中调用
//sonClass.g();
//小结:java中,private方法已经隐式的包含final关键字 所以final关键字有无并不重要
}
}
class FinalFatherClass{
private final void f(){
System.out.println("FinalFatherClass f()");
}
private void g(){
System.out.println("FinalFatherClass g()");
}
}
class SonClass extends FinalFatherClass{
private final void f(){
System.out.println("SonClass f()");
}
private void g(){
System.out.println("SonClass g()");
}
}
本文介绍final关键字,分别介绍了:
final关键字修饰变量,将变量变成常量,一般用来设置全局变量;
final关键字修饰类,将类变为不可以被继承的类;
final关键字修饰方法,将方法变为不可被重写的方法(但是可以被继承,只要是在该方法的访问控制权限允许的情况下);
最后讨论final关键字和访问控制权限的关系,对比了private和final,从某种意义上来说,final是介于protected和private之间的一种访问权限(虽然不准确,但是至少可以这样理解)。
Java中单继承多实现,先继承后实现(即当一个类既要继承又要实现的时候,顺序是先继承后实现 eg: extends A implements B)。
class SuperA {
}
class SuperB{
}
class Sub extends SuperA{//类继承类 只能继承一个类 单继承
}
interface InterfaceA {
}
interface InterfaceB{
}
class Sub implements InterfaceA,InterfaceB{//类实现接口 可以实现多个接口 Java多实现
}
接口继承接口容易被人遗忘,一般我们只记得类继承类和类实现接口,但接口直接也可以相互继承,而且还是多继承。
interface InterfaceA {
}
interface InterfaceB{
}
interface InterfaceC extends InterfaceA,InterfaceB{//接口继承接口 可以多继承
}
this表示当前类所指对象,super表示父类对象的引用
代码示意:
public class Test_thisAndSuper {
public static void main(String[] args) {
System.out.println("=====无参构造函数=====");
new BallGame();
System.out.println("=====带参构造函数=====");
new BallGame("basketBall");
}
}
class Game {
public Game() {
System.out.println("Game non-parameter constructor");
}
public Game(String name) {
System.out.println("Game parameter constructor: " + name);
}
}
class BallGame extends Game {
public BallGame() {
super();// 此行代码 可有可无 Java中,子类构造函数可以隐式调用父类无参构造函数
System.out.println("BallGame non-parameter constructor");
}
public BallGame(String name) {
super(name);
System.out.println("BallGame parameter constructor: " + name);
}
}
输出结果:
=====无参构造函数=====
Game non-parameter constructor
BallGame non-parameter constructor
=====带参构造函数=====
Game parameter constructor: basketBall
BallGame parameter constructor: basketBall
public class Test1 {
public static void main(String[] args) {
System.out.println("=====无参构造函数=====");
new BallGame();
System.out.println("=====带参构造函数=====");
new BallGame("basketBall");
}
}
class Game {
public Game() {
System.out.println("Game non-parameter constructor");
}
public Game(String name) {
System.out.println("Game parameter constructor: " + name);
}
}
class BallGame extends Game {
public BallGame() {
super();// 此行代码 可有可无 Java中,子类构造函数可以隐式调用父类无参构造函数
System.out.println("BallGame non-parameter constructor");
}
public BallGame(String name) {
// super(name);
System.out.println("BallGame parameter constructor: " + name);
}
}
运行结果:
=====无参构造函数=====
Game non-parameter constructor
BallGame non-parameter constructor
=====带参构造函数=====
Game non-parameter constructor
BallGame parameter constructor: basketBall
代码示意:
public class Test_thisAndSuper {
public static void main(String[] args) {
System.out.println("=====无参构造函数=====");
BallGame _ballGame_noParameter=new BallGame();
System.out.println("=====带参构造函数=====");
new BallGame("basketBall");
System.out.println("=====打印字段=====");
_ballGame_noParameter.displayField();
}
}
class Game {
protected String _description="This is an interesting game";
public Game() {
System.out.println("Game non-parameter constructor");
}
public Game(String name) {
System.out.println("Game parameter constructor: " + name);
}
}
class BallGame extends Game {
protected String _description="This is an interesting ballgame";
public BallGame() {
super();// 此行代码 可有可无 Java中,子类构造函数可以隐式调用父类无参构造函数
System.out.println("BallGame non-parameter constructor");
}
public BallGame(String name) {
super(name);
System.out.println("BallGame parameter constructor: " + name);
}
public void displayField(){
System.out.println("父类字段: "+super._description);
System.out.println("子类字段: "+this._description);
}
}
输出结果:
=====无参构造函数=====
Game non-parameter constructor
BallGame non-parameter constructor
=====带参构造函数=====
Game parameter constructor: basketBall
BallGame parameter constructor: basketBall
=====打印字段=====
父类字段: This is an interesting game
子类字段: This is an interesting ballgame
代码示意:
public class Test_thisAndSuper {
public static void main(String[] args) {
System.out.println("=====无参构造函数=====");
BallGame _ballGame_noParameter=new BallGame();
System.out.println("=====带参构造函数=====");
new BallGame("basketBall");
System.out.println("=====打印字段=====");
_ballGame_noParameter.displayField();
System.out.println("=====打印方法调用=====");
_ballGame_noParameter.displayFunction();
}
}
class Game {
protected String _description="This is an interesting game";
public Game() {
System.out.println("Game non-parameter constructor");
}
public Game(String name) {
System.out.println("Game parameter constructor: " + name);
}
protected void playing() {
System.out.println("This game is so interesting");
}
}
class BallGame extends Game {
protected String _description="This is an interesting ballgame";
public BallGame() {
super();// 此行代码 可有可无 Java中,子类构造函数可以隐式调用父类无参构造函数
System.out.println("BallGame non-parameter constructor");
}
public BallGame(String name) {
super(name);
System.out.println("BallGame parameter constructor: " + name);
}
public void displayField(){
System.out.println("父类字段: "+super._description);
System.out.println("子类字段: "+this._description);//此处this可以省略
}
protected void playing() {
System.out.println("This ballgame is so interesting");
}
public void displayFunction(){
System.out.print("父类方法: ");
super.playing();
System.out.print("子类方法: ");
this.playing();//此处this可以省略
}
}
输出结果:
=====无参构造函数=====
Game non-parameter constructor
BallGame non-parameter constructor
=====带参构造函数=====
Game parameter constructor: basketBall
BallGame parameter constructor: basketBall
=====打印字段=====
父类字段: This is an interesting game
子类字段: This is an interesting ballgame
=====打印方法调用=====
父类方法: This game is so interesting
子类方法: This ballgame is so interesting
子类构造函数中可以同时出现super和this关键字,但是super和this不能同时调用构造函数,代码示意:
public class Test_thisAndSuper {
public static void main(String[] args) {
System.out.println("=====无参构造函数=====");
BallGame _ballGame_noParameter=new BallGame();
System.out.println("=====带参构造函数=====");
new BallGame("basketBall");
System.out.println("=====打印字段=====");
_ballGame_noParameter.displayField();
System.out.println("=====打印方法调用=====");
_ballGame_noParameter.displayFunction();
}
}
class Game {
protected String _description="This is an interesting game";
public Game() {
System.out.println("Game non-parameter constructor");
}
public Game(String name) {
System.out.println("Game parameter constructor: " + name);
}
protected void playing() {
System.out.println("This game is so interesting");
}
}
class BallGame extends Game {
protected String _description="This is an interesting ballgame";
public BallGame() {
super();// 此行代码 可有可无 Java中,子类构造函数可以隐式调用父类无参构造函数
System.out.println("BallGame non-parameter constructor");
}
public BallGame(String name) {
super(name);
System.out.println("BallGame parameter constructor: " + name);
}
public BallGame(String test1,String test2){
//super(test1);
//this(test1); super()和this()都要放在第一行 自相矛盾 编译时报错
//小结:super和this可以同时出现,即使是在子类构造方法中也可以同时出现,但是不同同时调用构造方法,
//理论解释:因为在一个构造方法中,只能访问一次其它的构造方法(不管是父类的还是子类的)所以此时不能同时用super和this关键字来调用构造方法,只能根据需求选其一。
//简单理解:调用构造函数时,两个都要放第一,自相矛盾
}
public void displayField(){
System.out.println("父类字段: "+super._description);
System.out.println("子类字段: "+this._description);//此处this可以省略
}
protected void playing() {
System.out.println("This ballgame is so interesting");
}
public void displayFunction(){
System.out.print("父类方法: ");
super.playing();
System.out.print("子类方法: ");
this.playing();//此处this可以省略
}
}
输出结果:
因不可同时调用父类构造函数和子类构造函数,无输出结果
小结(面试金手指,this与super同时出现)
1、super和this可以同时出现,即使是在子类构造方法中也可以同时出现,但是不同同时调用构造方法;
2、理论解释:因为在一个构造方法中,只能访问一次其它的构造方法(不管是父类的还是子类的)所以此时不能同时用super和this关键字来调用构造方法,只能根据需求选其一;
3、简单理解:调用构造函数时,两个都要放第一,自相矛盾。
定义:static修饰的域、方法、代码块为类所有,而不是为对象所有;
调用:可以使用类名调用(亦可使用对象名调用);
变量加载顺序:static域加载时仅加载一次(基础面试题第一篇,变量加载顺序)。
第一点,static方法、代码块内可以只能出现static域、方法、代码块,最常见的就是main方法,static方法只能出现static变量。
第二点,非static方法只能由对象名调用调用,因为非static方法只有在对象存在时才有意义。
final关键字三个特性:final修饰的变量为常量、final修饰的类不可继承、final修饰的方法不可重写。
第一,final修饰的变量为常量
对于final修饰的变量,应该对基本类型和引用类型分开讨论:
基本类型为栈内存(-128~127情况下),一旦被final关键字修饰,其变量属性变为只读,不再进行写操作,否则编译报错。
引用类型为堆内存,一旦被final关键字修饰,则引用不再改变,但是引用所指向的对象是可以被修改的,Java语言并未提供任何方式使用对象恒定不变。示意代码如下:
FinalData finalData=new FinalData();
//finalData.value=new Value(33); //编译报错 value为final类型
finalData.value.i++; // 编译通过 value所指向的对象可以修改
final变量的两个初始化时机:final变量定义时初始化、final变量构造函数中初始化(空白final)
第二, final修饰的类不可继承
第三,final修饰的方法不可重写,但是可以被继承,子类可见
ps:方法是否被final修饰与方法的访问权限是两回事,没有任何关系,被final修饰的方法和未被final修饰的方法都可以自由的指定访问权限。
附加:对于final方法 private<final<protect (仅适用于方法)
protect修饰的方法在子类中可见,所有可以被子类继承,亦可以被子类重写;
final修饰的方法可以被子类继承,但不可被子类重写(这里final方法的访问权限为默认的default、protected、public均可,只要保证子类可见即可);
private修饰的方法由于仅本类可见,故不能被子类继承,亦不能被子类重写;
ps:对于方法,所有被private关键字修饰的方法都隐式的被final关键字修饰,可以对private方法添加final关键字,但是这种做法没有任何意义。
类继承类(单继承)
类实现接口(多实现)
接口继承接口(多继承)
this表示当前类所指对象,super表示父类对象的引用
第一,对于构造函数,对于super() 和 super(xxx) 默认调用父类无参构造函数
第二,子类字段和父类字段
public void displayField(){
System.out.println("父类字段: "+super._description);
System.out.println("子类字段: "+this._description);
}
第三,子类方法和父类方法
public void displayFunction(){
System.out.print("父类方法: ");
super.playing();
System.out.print("子类方法: ");
this.playing();//此处this可以省略
}
第四,this与super同时出现
1、super和this可以同时出现,即使是在子类构造方法中也可以同时出现,但是不同同时调用构造方法;
2、理论解释:因为在一个构造方法中,只能访问一次其它的构造方法(不管是父类的还是子类的)所以此时不能同时用super和this关键字来调用构造方法,只能根据需求选其一;
3、简单理解:调用构造函数时,两个都要放第一,自相矛盾。
文章浏览阅读1.3k次。问题:权限不对的。_bad owner or permissions
文章浏览阅读411次,点赞8次,收藏3次。对于使用macOS系统的用户来说,长时间的使用会不可避免地产生一定量的系统垃圾,这些垃圾文件包括但不限于应用缓存、系统日志文件、用户日志文件、残留的应用支持文件等。Mac怎么清理系统垃圾,通过上述方法,用户可以有效清理macOS系统中的垃圾文件,释放硬盘空间,提高系统性能。除了手动清理,市面上也有许多专门为macOS设计的第三方清理工具,在众多清理工具中,CleanMyMac X是比较受用户欢迎的。清理垃圾文件是保持系统性能的重要步骤,用户应养成定期清理系统垃圾的习惯。点击“系统垃圾”,开始扫描。
文章浏览阅读2.5w次,点赞20次,收藏126次。font-size:设置字体大小:该属性值的单位可以使用相对单位和绝对单位,推荐使用相对定位中的px。(浏览器能够识别的最小像素是12px)p{ font-size:20px;}常见尺寸单位:font-family:设置字体:如果需要设置多个字体样式,则属性值可以写多个中间用逗号隔开即可,需要知道的是浏览器会从第一个字体属性值找,直到找到自己设备有的字体显示,自己设备没有的字体,按设备默认字体显示,推荐系统默认字体。p{ font-family:"微软雅黑",Arial;}_css设置字体大小
文章浏览阅读1k次。SonarQube+SonarScanner搭建_java项目需要安装sonar scanner
文章浏览阅读185次。Problem\mathrm{Problem}ProblemYou are given a tree (an undirected connected graph without cycles) and an integer sss .Vanya wants to put weights on all edges of the tree so that all weights are non-negative real numbers and their sum is sss . At the same_cf1085d
文章浏览阅读1.1w次,点赞90次,收藏287次。vue实战小项目系列,一个前端项目从0到1的保姆级教学。很适合后端或者才入门的同学看!_404页面前端代码
文章浏览阅读9.1k次。OracleEnterpriseManager(Oracle企业管理器,简称OEM)是通过一组Oracle程序,为管理分布式环境提供了管理服务。OEM包括了一组DBA工具,一个repository,以及一个图形化显示的控制台。OEM控制台与每一个服务器上的智能化**(IntelligentAgent)相对应。 智能化**能够监控系统的特定事件并且执行任务(作业)就象你在系统本地一样。事件和作业的_oemm oracle
文章浏览阅读357次,点赞3次,收藏7次。随着血液的流通,移植的猪肾开始呈现健康的粉红色,并履行其功能,产生尿液。这一成功的瞬间,手术室内的15名移植专家目睹了这一令人赞叹的景象,并在周四的新闻发布会上由Kawai博士宣布了这一喜讯,他们以热烈的掌声庆祝了这一成就,这不仅标志着手术的胜利完成,也展示了医学领域在治疗重大疾病上取得的重大进展。在麻省总医院,一支专业的医疗团队正在进行一项关键的手术操作:将一颗经过多次基因编辑的猪肾逐步植入病人Slayman的循环系统内,这一过程由于患者自身存在的疾病而显得尤为复杂,因为其血管条件并不理想。
文章浏览阅读46次。此外,云平台还提供丰富的算法库和工具,支持用户上传和部署自己的算法模型,以满足不同用户的需求。烟火识别系统基于智能视频分析技术,能够识别监控区域内的烟雾和火焰,并进行动态识别,包括烟雾和火焰的状态转换,例如从有到无、从小到大、从大到小、从小烟到浓烟。它能够实时分析并报警,不依赖其他传感设备,直接对监控区域内的烟雾和火焰进行准确识别,并及时将报警信息推送给相关的管理和安全人员,以便及时应对和处理。此外,平台还提供丰富的算法库和工具,并支持用户上传和部署自定义算法,提升了平台的灵活性和个性化能力。
文章浏览阅读245次,点赞5次,收藏8次。此方法返回表示数字对象的字符串,达到指定的精度(precision)。_toprecision函数
文章浏览阅读3.8k次。 摘 要 介绍了射频卡的工作原理及结构,并给出了使用多线程技术实现射频卡监听和读写的方法及其在C#下的具体实现。指出利用多线程实现射频卡的监听和读写能够提高射频卡读写程序的并发性、可靠性和运行效率,从而提高整个应用系统的性能。 关键词 多线程 C# 射频卡 性能 1 引言 射频卡又称非接触式IC卡, 是世界上最近几年发展起来的一项新技术, 它成功的_如何用c++读取射频卡
文章浏览阅读2.1k次。SITL仿真环境搭建ardupliot源码下载与编译首先需要安装Ardupliot开源飞控的开发环境,参考这个知乎博主的文章:链接我的安装环境 ubuntu20.04。先下载Ardupilot源码,然后进入ardupilot文件夹更新一下子模块 git clone https://github.com/ArduPilot/ardupilot cd ardupilot git submodule update --init --recursive之后,根据网上大多数文章推荐的方法运行对应的sh_sitl仿真