Skip to content

day03【final、static、匿名内部类】

今日内容
java
1.关键字 final[重点]
2.关键字 static[重点]    静态关键字
3.抽象类   模板模式

第一章 final 关键字

java
final关键字概念:
   含义:最终的,可以修饰类、成员变量、成员方法。

1.0 引入案例

java
package com.itheima.demo01_final;
/*
  余则成
     我党  情报人员

      潜伏在重庆政府

 */
public class YuZeCheng {
     /*
       这份情报最好要做成 谁都无法修改的!!
       final  最终的 不能被更改
          final修饰的方法 叫做最终方法
            只能被继承 不能被重写
      */
    public final void qingBao(){
        System.out.println("蒋介石要逃跑....");
    }
}
package com.itheima.demo01_final;

/*
  余则成
  儿子  小余 继承 余则成
 */
public class XiaoYu  extends YuZeCheng {

    // 小余 在 去情报站的路上 被追杀...
    // 军统----女特务   精神欺骗
//    @Override
//    public void qingBao(){
//        System.out.println("蒋介石爱种梧桐树!");
//    }

}
package com.itheima.demo01_final;

public class FinalDemo {
    // 情报站
    public static void main(String[] args) {
        // 原本余则成要来送情报,但是被抓了
        // 把情报给了他儿子 小余
        // -----经过很多地方----最终要到达情报站-
        XiaoYu xiaoYu = new XiaoYu();

        xiaoYu.qingBao();
    }
}

结论:final 修饰的方法不能被重写。

1.1 final 关键字

java
final: 中文意思 最终,不能发生更改的。
   修饰方法,修饰的方法被称为最终方法,可以被继承不能被重写。
   修饰类,被称为最终类,不能被继承。
   修饰变量(局部,成员)  只能赋值一次,赋值之后不能值被更改。
                               基本 数值 引用 地址值

1.2 final 的作用介绍

  • final 修饰类

    java
    /**
     * 被final修饰的类 称为最终类,不能被继承!
     */
    public final class LiLianYing {
    }
    public class LiYingLian extends LiLianYing{//报错 原因是final修饰的类不能被继承
    }
  • final 修饰方法

    java
    被final修饰的方法称为最终方法,也可以叫做最牛逼的方法,不能被重写!
    public class Fu {
    
        public final void show(){}
    
    }
    public class Zi extends Fu{
    
        public void show(){}//这里报错 原因时被final修饰的方法不能被重写
    }
  • final 修饰局部变量-基本类型

    java
       //这是一个局部位置  被final修饰只能赋值一次
           final int c = 1;
    
            System.out.println(c);
    
    //        c=2;//加了final 这里报错 原因是 被final修饰的变量只能被赋值一次
            System.out.println(c);
  • final 修饰引用类型的变量

    java
      // 创建对象 有地址0x11
            // dog 的值 是 0x11
            final Dog dog = new Dog();
            dog.age=10;// 给0x11空间中的age赋值
            dog.age = 11;//给0x11空间中的age 赋值
                  // 空间的age赋值了两次
    
    //        dog = new Dog();// dog的值发生改变了 变成0x22
            // 总结   final如果修饰基本类型变量  数值不能变
                   //final修饰引用类型变量  地址值不能变

    final 修饰了局部变量

    java
    特点:
       如果被修饰的变量是基本类型,数值不能变。
       如果被修饰的变量是引用类型,地址值不能变。
  • final 修饰成员变量

    java
    被final修饰的成员变量,也是称为常量,只能赋值一次。而且在初始化之前 必须完成赋值。

1640744380801

第二章 static 关键字

2.1 static 修饰成员可以被多个对象共享

java
package com.itheima.static01;

public class NBAPlayer {
    String name;//姓名
   static String country;//国籍

    public void show(){
        System.out.println(name+"的国籍是:"+country);
    }
}
package com.itheima.static01;

/**
 *  每new一次 都会在 堆空间 构建一个地址
 *
 *     变量是内存中的一小块区域。
 *     现在有三个对象
 *       每个对象都有 两块小区域
 *       player1    name 詹姆斯 country 美国
 *       player2    name 杜兰特 country 美国
 *       player3    name 林书豪 country 美国
 *     运动员名字不一样申请三个空间是可以理解的
 *     国籍是一样的 还申请三个 有些浪费
 *
 *     能不能 只申请一个空间,让这个三个对象实现共享!
 *     申请到类中合适?
 *     java提供了一个关键 static 表示 与类相关的
 *       特点
 *          可以被多个对象共享!!
 *
 *      country被static修饰
 *
 *      如果说 可以被多个对象共享
 *        player1设置了国籍之后 player2 player3 就不用设置了。
 *
 *      player1设置国籍叫 美国  player2 player3没有设置国籍
 *      但是运行之后 发现  player2 player3有国籍了。
 *
 */
public class Demo {
    public static void main(String[] args) {
        //创建球员对象
        NBAPlayer player1 = new NBAPlayer();
        player1.name="詹姆斯";
        player1.country="美国";
        player1.show();

        NBAPlayer player2 = new NBAPlayer();
        player2.name="杜兰特";
       // player2.country="美国";
        player2.show();

        NBAPlayer player3 = new NBAPlayer();
        player3.name="林书豪";
        //player3.country = "美国";
        player3.show();
    }
}

1640747793232

1640747776536

2.2 static 关键字 内存图

加入了一下代码

java
 System.out.println("刚才的国籍赋值由player1赋值,所以结果都是player1赋值后的结果");
        // 最近篮球没有进世界杯 所以蓝联规划 林书豪
        // 派马保国 说服 他
        NBAPlayer.country = "中华人民共和国";
        //查看一下 player3
        player3.show();
        //再查看一下 player2 player1
        player1.show();
        player2.show();

效果:

1640749809575

1640749753911

1640759428115

通过内存图记住几个结论

java
1:类只加载一次。静态成员属于类,随着类的加载而加载,加载一次,优先于对象存在。
2:被static修饰的成员,不属于某个对象,在静态区域。属于类,所以静态成员可以叫做类成员。
3:静态成员可以被对象共享使用。

注意 以后调用静态内容 建议 直接使用类名调用,因为本身就是属于类。

2.3 静态修饰符的使用

java
静态可以修饰类中成员
    成员变量--静态变量
      格式  static 类型 变量名 ;
    成员方法--静态方法
     格式 就是比之前的方法多了一个 static
        public static 返回值类型 方法名(..){
           return ...;
        }
    修饰 代码块
    什么是代码块  {}
    static{ } 静态代码块

修饰后的成员变量成员方法怎么调用呢?

java
类名.属性名   类名.方法名(..)
举例
   System.out
   Math 数学类 进行数学运算的,这个类的方法都是static修饰的。
   Math.ceil() 向上取整。
   Arrays.toString();

只要大家发现 类名能直接调用的方法都是静态的。

java
package com.itheima.static02;

public class MyMath {

    //定义了一个 静态的变量 pai
    public static  double pai = 3.14;

    public static int sum(int a,int b){
        return a+b;
    }
 }
java
package com.itheima.static02;

public class Demo {
    public static void main(String[] args) {

        //静态可以直接类名调用
        System.out.println(MyMath.pai);

        int sum = MyMath.sum(3, 4);
        System.out.println(sum);
    }
}

2.4 注意事项

在一个静态方法中能否直接调用一个非静态变量?

不能。 静态--秦始皇 非静态---现在人

静态只能调用静态!

非静态方法中能不能调用静态内容:可以

2.5 静态代码块

代码块:就是大括号括起来的内容 {}

java
if(){

}

for(){

}

**静态代码块: 代码块前面加 static **

java
static{
    写代码区域
}
位置: 类中方法外!!
java
package com.itheima.static03;

public class Student {

    //定义一个 静态代码块
    static{
        System.out.println("静态代码执行了");
    }


    public Student(){
        System.out.println("student类的无参构造");
    }

    public void show(){

    }
}
package com.itheima.static03;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {
        //静态代码块怎么调用 能不能调用
        // 无法调用
      // 静态修饰成员 随着类的加载而加载

//        new Student();//当这个对象出现的时候 是不是类已经加载完了
        Class.forName("com.itheima.static03.Student");
        // 上面一句话 就是把 com.itheima.static03.Student 加载到内存中
        new Student();
        new Student();
        new Student();
    }
}

1640761404113

结论:

java
a:随着字节码文件(类)的加载,而执行,只执行一次。
b:优先于对象出现,所以肯定比构造早。
作用:
   在将来的工具类中,用于读取配置文件。
   对于程序中只需要加载一遍的内容,可以采用静态代码块。

第三章 内部类

3.1 什么是内部类

概念:就是在一个类的内部定义一个类

java
public class A{
    private String a;
    public void show(){
        class C{}
    }

    //成员内部类
    class B{

    }
}
B是A的内部类,A是B的外部类。

内部类分为:成员内部类和局部内部类。在成员位置的就是成员内部类,在局部位置就是局部内部类。

3.2 成员内部类 的访问特点

java
package com.itheima.innerclass01;

public class ZhiZunBao {
    //成员属性
    private String lover = "紫霞仙子";
    //成员方法
    public void tiaoya(){
        System.out.println("我爱紫霞仙子");
        System.out.println("我爱白晶晶");
    }

    //成员内部类---定义了一个心脏
    class Heart{
        private String wife = "白晶晶";
        //内部类的 方法
        public void speak(){
            System.out.println("最爱的人是谁:"+lover);//内部类访问外部类的成员变量
            tiaoya();//内部类访问外部类的成员方法
            System.out.println("你的妻子是:"+wife);
        }
    }
}
java
package com.itheima.innerclass01;

public class Demo {
    public static void main(String[] args) {
        //直接创建 Heart对象?
//    Heart heart = new Heart();内部类无法单独创建对象
        //先 创建外部类对象
//        ZhiZunBao zhiZunBao = new ZhiZunBao();
//        ZhiZunBao.Heart heart = zhiZunBao.new Heart();
        //简化形式
        ZhiZunBao.Heart heart = new ZhiZunBao().new Heart();

        heart.speak();
    }
}

结论

java
1:内部类中可以直接访问到外部类成员。
2:想要调用内部类成员,必须先创建外部类对象再创建内部类对象。
创建格式   外部类.内部类 变量名= new 外部类().new 内部类();

3.3 内部类编译之后 会产生.class 文件

java
ZhiZunBao$Heart.class
      内部类编译之后形成了.class文件。

1640762953511

作用:在一个类的内部创建一个类,只允许当前类用这个类,别人无法直接访问。

第三章 匿名内部类

产生的结果,也是一个.class 文件,这不过这个.class 文件没有具体的名字。

java
package com.itheima.nonameinnerclass;

public  abstract  class Animal {

  public  abstract void eat();
}
java
package com.itheima.nonameinnerclass;

import javafx.scene.AmbientLight;

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
java
package com.itheima.nonameinnerclass;

public class Demo {

    public static void main(String[] args) {
        //我想养一只动物
        // 不能直接实例化抽象类 咋办?
        /*
          1: 创建一个类 继承 Animal
          2:重写了 抽象方法 eat()
          3: 创建Animal子类对象
         */
       Animal animal = new Cat();

        animal.eat();
        /*
          能不能不在外面创建类的基础上 完成对象的实例化?
          只能使用内部类
         */
        class Dog extends Animal{
             public void eat(){
                 System.out.println("狗吃you");
             }
        }
        Animal a2 = new Dog();
        a2.eat();
        // 我想要动物  是猫是狗重要吗 不重要  重写的方法才重要
        //能不能再简单直接点 来一个 只突出 重写方法的 子类对象
        Animal a3 = new Animal() {
            @Override
            public void eat() {
                System.out.println("老虎吃鸡");
            }
        };
        // 产生了 Animal的子类对象  (以匿名内部类的形式出现)
        a3.eat();
    }
}

作用

匿名内部类 本质 是快速的构建一个接口或者类的子类对象!

为啥叫匿名内部类,在产生这个子类对象的时候,临时的产生一个类,这个类没有名字。

格式

java
new 接口名/类名(){
   把所有抽象方法都要重写。
}

效果

1640764731874

Released under the MIT License.