zoukankan      html  css  js  c++  java
  • 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关键字一样)。

  • 相关阅读:
    读《大道至简》有感(结束)
    super一些要点
    读《大道至简》有感(六)
    随机数数组 框图输出
    读《大道至简》有感(五)
    《需求工程》阅读笔记03
    《需求工程》阅读笔记01
    天明闹钟开发过程2
    《需求工程》阅读笔记02
    天明闹钟开发过程1
  • 原文地址:https://www.cnblogs.com/winlrou/p/4004979.html
Copyright © 2011-2022 走看看