• Java学习笔记五:复用类


    当我们在使用第三方或者其他人已经写好的类时,通常有两种方法:

    (1).组合:在新的类中产生现有类的引用。

    (2).继承:按照现有类的类型创建新类。

    1.组合

    简单理解就是新类中,创建一个变量,变量的引用为现有类。

    我们在很多场景下都是用到组合,如:

    public class Lesson_04_Extend
    {
        private Extend1 extend1; // 组合方式,创建成员变量(UML 组合关系)
        
        public void print(Extend1 extend2) // (UML 依赖关系)
        {
            
        }
    }
    
    class Extend1
    {
        
    }

    上述例子例子中还特别说明了下在uml类图中组合和依赖的关系

    组合:一般作为变量,是一个与整体关系非常强的表示方式,生命周期与整体一致;

    依赖:一般作为方法参数,与整体关系较弱,生命周期随着方法调用结束和结束,意味着与整体关系不这么密切。

    2.继承

    顾名思义,就是创建新类是拥有父类的特性。

    当我们创建一个类是,如果没有显式继承某个父类,则会隐式的继承至Object。

    (1)当新类继承父类时,就会拥有父类中 public 或者 protect 的属性或者方法。

    (2)super 关键字表示超类的意思,主要作用是对父类方法的引用

    1.想要使用父类带参数的构造函数时,可以使用super(x);

    2.创建新类时,使用super.xxx()使用父类的方法。

    public class Lesson_04_Extend
    {
        private Extend1 extend1; 
        
        public Lesson_04_Extend(int i)
        {
            System.out.println("Lesson_04_Extend.Lesson_04_Extend()" + i);
        }
        
        public void print(Extend1 extend2)
        {
            System.out.println("Lesson_04_Extend.print()");
        }
        
        public String printStr()
        {
            return "Lesson_04_Extend";
        }
    }
    
    class Extend1 extends Lesson_04_Extend
    {
        public Extend1(int i)
        {
            super(i); // 父类构造函数
            super.printStr(); // 父类方法
        }
        
        /**
         * 重写父类方法(区别重载)
         */
        @Override
        public String printStr()
        {
            return "Extend1"; 
        }
    }

    3.final关键字

    final关键字表示“这是无法改变的”。通常有两个理由不想做出改变:1.设计(最常用的);2.效率(不常用,在jdk6,7不明显)

    1.final数据

    在编程时,有时数据的恒定不变时很有用的,如:

    (1)一个永不改变的编译时常量

    (2)一个在运行时被初始化的值,而你不希望他改变

    用代码理解,如:

    class FinalDemo
    {
        public static final String FINAL_CONSTANT = "final constant"; // 编译时常量
        
        private final String final_init = "final_init"; // 初始值
    }

    2.当使用static final 时,系统内存会为我们在栈中开辟一个不能改变的存储空间,通常会使用在基本数据类型和引用上

    public static final int INT_STATIC = 100; // 基本数据类型
        
    public static final Lesson_04_Extend lessson_4 = new Lesson_04_Extend(1); // 引用类型

    这里说明下:当我们使用引用类型时,不变的是在栈中存储的引用,而易用指向堆中的的数据是可以改变的。

    这里举个例子:当我们获取身份证的时候,如果没有特殊情况,这个身份证就永远不会改变(如照片,住址),但是身份证上的人是可以改变的(如短头发,长头发等等)。

    下面代码用的是“Java编程思想”的例子,由于书上说明太乱,这里是自己理解描述:

    class FinalData
    {
        private static Random rand = new Random(47);
        
        private String id;
        
        public FinalData(String id)
        {
            this.id = id;
        }
        
        // Can be compile-time constants:
        private final int valueOne = 9;
        
        private static final int VALUE_TWO = 99;
        
        // Typical public constant:
        public static final int VALUE_THREE = 39;
        
        // Cannot be compile-time constants:
        private final int i4 = rand.nextInt(20);
        
        static final int INT_5 = rand.nextInt(20);
        
        private Value v1 = new Value(11);
        
        private final Value v2 = new Value(22);
        
        private static final Value VAL_3 = new Value(33);
        
        // Arrays:
        private final int[] a =
        {
            1, 2, 3, 4, 5, 6
        };
        
        public String toString()
        {
            return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
        }
        
        public static void main(String[] args)
        {
            FinalData fd1 = new FinalData("fd1");
            // ! fd1.valueOne++; // Error: can't change value
            fd1.v2.i++; // Object isn't constant!
            fd1.v1 = new Value(9); // OK -- not final
            for (int i = 0; i < fd1.a.length; i++)
                fd1.a[i]++; // Object isn't constant!
            // ! fd1.v2 = new Value(0); // Error: Can't
            // ! fd1.VAL_3 = new Value(1); // change reference
            // ! fd1.a = new int[3];
            System.out.println(fd1);
            System.out.println("Creating new FinalData");
            FinalData fd2 = new FinalData("fd2");
            System.out.println(fd1);
            System.out.println(fd2);
        }
    }

    输出结果:

    fd1: i4 = 15, INT_5 = 18
    Creating new FinalData
    fd1: i4 = 15, INT_5 = 18
    fd2: i4 = 13, INT_5 = 18

    (1)首先,肯定先执行 main 函数,在 main 函数中,初始化 FinalData , 初始化结果:

    1.1 下面三个先按顺序执行,同时初始化 VAL_3 

    private static final int VALUE_TWO = 99;
    public static final int VALUE_THREE = 39;
    private static final Value VAL_3 = new Value(33);

    这里说明下:上面三个值是由于是在编译时就知道它们的值,所以在定义变量时需要用到大写+下划线;

    1.2 初始化其他非static成员变量

    这里说明下,final 前面加上static 和 不加 static 的区别:就初始化而言,执行的先后顺序有差别而已。

    private final int valueOne = 9;
    private static final int VALUE_TWO = 99;

    1.3 构造函数初始化,将id 赋值给成员变量。

    (2)执行fd1;

    2.1 执行v2.i++ 

    fd1.v2.i++;  // 值是23

    如果这个时候声明,编译报错

    // fd1.v2 = new Value(22); // Error, final Data

    2.2 引数组也是引用,指向引用内容的值是可以改变的(只是指向数据的引用不能在指向其他引用)

    数组值为:

    { 2, 3, 4, 5, 6, 7};

    (3)声明fd2,静态成员不会再次初始化,这里注意的是i4的值,由于fd1,fd2是两个不同的引用,在堆中有两个不同的空间,

    所以,在执行i4的时候有两个值,而 i5只有一个(静态。)

    3.空白final

    指被声明为final担忧为给定初始值的域。

    可以在构造函数,或者方法调用时给final指定的对象附上初始值

    class Poppet
    {
    }
    
    class BlankFinal
    {
        final int i = 0; // Initialized final
        
        final int j; // Blank final
        
        final Poppet p; // Blank final handle
        // Blank finals MUST be initialized
        // in the constructor:
        
        BlankFinal()
        {
            j = 1; // Initialize blank final
            p = new Poppet();
        }
        
        BlankFinal(int x)
        {
            j = x; // Initialize blank final
            p = new Poppet();
        }
        
        public static void main(String[] args)
        {
            BlankFinal bf = new BlankFinal();
        }
    }

    4.final参数

    在方法中指定final,表明方法中指定的引用时不能改变的。

    class FinalArgument
    {
        void with(final BlankFinal g)
        {
            // ! g = new Gizmo(); // Illegal -- g is final
        }
        
        void without(BlankFinal g)
        {
            g = new BlankFinal(); // OK -- g not final
        }
    }

    5.final类

    当类使用final时,表明不打算让其他类继承这个类(与C#中的sealed关键字一样)。

  • 相关阅读:
    PNG文件格式具体解释
    opencv2对读书笔记——使用均值漂移算法查找物体
    Jackson的Json转换
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 装箱问题
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 单词接龙
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 方格取数
    Java实现 蓝桥杯VIP 算法训练 单词接龙
  • 原文地址:https://www.cnblogs.com/winlrou/p/4004979.html
Copyright © 2020-2023  润新知