• Java学习笔记14(面向对象七:final、static)


    final:意为最终,不可变,是一个修饰词

    有时候一个类地功能被开发好了,不想让子类重写,修改,这里就会用到final关键字

    final修饰类:

    不可以被继承,但是可以继承其他类

    示例:

    public final class Fu {
        public void show(){
            System.out.println("最终类的方法");
        }
        //这个类不能被继承
        //使用方法不变
    }
    public class Test {
        public static void main(String[] args) {
            Fu f = new Fu();
            f.show();
        }
    }

    final修饰方法:

    不可以被子类重写

    示例:

    public class Fu {
        public final void show(){
            System.out.println("父类的最终方法");
        }
        public void function(){
            System.out.println("父类的一般方法");
        }
    }
    public class Zi extends Fu {
        public void function(){
            System.out.println("子类重写父类的一般方法");
        }
        //不可以重写父类的show方法
    }
    public class Test {
        public static void main(String[] args) {
            Zi z = new Zi();
            //方法的使用方式没有改变
            z.function();
            z.show();
        }
    }

    final修饰的变量称为常量,只能被赋值一次:

    一次赋值,终身不变

    如果final修饰引用数据类型,那么保存变量的内存地址将终身不变

    final修饰成员变量:

    成员变量保存在堆内存中,是有默认值的,所以final修饰成员变量必须要赋值

    由于成员变量的赋值方式有两种:直接赋值;构造方法赋值,所以final修饰的成员变量可以选择其中一种进行赋值

    但是要保证只能被赋值一次

    示例:

    public class Person {
        //直接赋值(实际中建议这样方式):
        //final int age = 18;
        //构造方法赋值:
        final int age;
        public Person(int age){
            this.age = age;
        }
    }

    static:

    意义举例:

    一个学校里有一群学生对象,他们都有不同的姓名和年龄,但是他们的学校名都是相同的,

    创建学生对象的时候,成员变量中的学校名在每次新建对象的时候都会存入堆内存,但是每次存的数据都是相同的,造成了内存的浪费

    于是想到,能否将学校名提出来,放到某个地方,让多个对象共享,节省内存

    于是,出现了static关键字:

    静态多了一种调用方式

    被静态修饰的成员,可以被类的名字直接调用

    示例:

    public class Person {
        String name;
        static String className;
    }
    public class Test {
        public static void main(String[] args) {
            Person p1 = new Person();
            Person p2 = new Person();
            p1.name = "张三";
            p2.name = "李四";
            p1.className = "一班";
            //共享数据的特性:一处改,其他对象跟着改
            System.out.println(p2.className);
            System.out.println(Person.className);
        }
    }
    //输出:一班

    根据这个示例对static内存的分析:

    内存中,静态优先于非静态存在的

    1.Test.class文件中的main方法进入数据共享区(静态区),

    2.Person.class文件中的className变量进入数据共享区,并赋默认值null

    3.开始执行,运行main方法,JVM到静态区将main方法复制一份,压栈执行

    4.创建对象,堆中开空间存对象,成员变量跟随,静态不进入,因为静态变量早进入了静态区

    5.JVM到静态区,找到属于Person类的静态属性className,进行修改等操作

    静态的注意事项:

    静态不能调用非静态:

    原因:声明周期

    静态优先于非静态存在于内存在,无法调用不存在的

    比如古人无法访问现代人

    非静态可以调用静态

    比如现代人可以访问古人(可能有点不恰当...理解就行)

    静态不能用this,super方法,

    同样,静态在创建对象前就存在,不允许访问不存在的

    而在实际中,通常静态对静态,非静态对非静态

    示例:

    public class Student {
        private String name;
        private static int age;
        public static void function(){
            //System.out.println(name);
            //这里的静态方法不能调用非静态
        }
        public void show(){
            System.out.println(age);
            //非静态可以调用静态
        }
    }

    静态修饰应用场景:

    本身是一个成员修饰符,可以修饰成员变量,可以修饰成员方法

    多个事物之间是否存在共性数据?这里就可以将这个共性数据定义成静态

    只要方法没有调用过非静态成员,则将其定义为静态

     对象中的静态调用:

    这里是之前多态中的一个难点:

    示例:

    public class Fu {
        static int i = 1;
        public static void show(){
            System.out.println("父类的静态方法");
        }
    }
    public class Zi extends Fu {
        static int i = 2;
        public static void show(){
            System.out.println("子类的静态方法");
        }
    }
    public class Test {
        public static void main(String[] args) {
            Fu f = new Zi();
            System.out.println(f.i);
            f.show();
        }
    }
    /*输出:
    1
    父类的静态方法
    */
    
    /*
     多态中,编译看等号左边的,父类有编译成功,父类没有,编译失败
     运行看等右边的,
     如果是静态方法,运行的是父类中的静态方法
     如果是非静态方法,运行的是子类重写的非静态方法
     成员变量:
     无论静态非静态,编译运行都是父类的
     
     根本原因:静态属于类,不输入对象
     多态性是讨论对象的性质,而静态和对象无关,
    */

    最后,

    在开发中,有时候需要定义静态常量,并且常量名要求全大写,空格用_代替

    固定格式:public static final String THIS_NAME = "XXXX"

  • 相关阅读:
    数组作业:例题5.1.一个10个元素一维数组的赋值与遍历
    java子父类初始化顺序 (1)父类静态代码块(2)父类静态变量初始化(3)子类静态代码块(4)子类静态变量初始化(5)main(6)有对象开辟空间都为0(7)父类显示初始化(8)父类构造(9)子类显示初始化(10)子类构造
    如果实现接口的类只使用一次用处不大换为如下简便写法——匿名内部类
    1、实现接口的抽象类——适配器;2、代理公司的方法——功能更强大的包装类;3、接口的使用——工厂模式(高内聚低耦合)
    内部类的作用?1、抽象类中包含一个内部接口如何实现与调用 ;2、接口中包含一个内部抽象类如何调用
    接口的多态使用; 接口应用实例:U盘、打印机可以使用共同的USB接口,插入到电脑上实现各自的功能。
    接口的定义——默认加public abstract默认全局常量;与继承不同,子类可以同时实现多个接口;抽象类实现接口;接口继承接口
    EBCDIC to ASCII
    how to pass variable from shell script to sqlplus
    关于Insufficient space for shared memory file解决办法
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/8244541.html
Copyright © 2020-2023  润新知