首页 > 代码库 > 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 = 18Creating new FinalDatafd1: i4 = 15, INT_5 = 18fd2: 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 Data2.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关键字一样)。
Java学习笔记五:复用类