博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Reusing Classes
阅读量:6249 次
发布时间:2019-06-22

本文共 4791 字,大约阅读时间需要 15 分钟。

hot3.png

使用继承时子类的实例的初始化

子类实例初始化时,如果我们不显示调用父类的构造函数,编译器会先调用父类的默认的构造函数,顺着这个继承链向上一直到Object。如果子类的某个祖先类的构造函数被有参数的替换了,也没有提供无参的,那么必须在子类显示调用父类的有参数的构造函数,否则编译器会报错。

public class Test18 {	public static void main(String[] args) {		Cat cat = new Cat();                /×                    Animal                    Cat                ×/	}}class Animal{	Animal(){		System.out.println("Animal");	}}class Cat extends Animal{	Cat(){		System.out.println("Cat");	}}

在子类中overload父类的方法

在java中子类中overload父类的方法,如果父类的该方法本身有overload的方法时,在子类中这些方法还在;而在C++中父类的这些overload的方法不能访问了。

public class Test19 {	public static void main(String[] args) {		Man m = new Man();		m.eat();		m.eat(1);		m.eat(1.2);		m.eat("23");	}	}class People{	public void eat(){			}	public void eat(int a){			}	public void eat(String b){			}}class Man extends People{	public void eat(double d){			}}
#include 
using namespace std;class Father{public: void eat(){ } void eat(int a){ }};class Son:public Father{public: void eat(double d){ cout<
<
Upcasting

Upcasting指的是父类的引用指向子类的对象:

void test(Father f){}Son s = new Son();test(s);//Upcasting
当我们在Composition和Inheritence之间选择时,只需要判断需不需要用到Upcasting,如果需要则使用继承。

final关键字

final data

final data可以分为两类:

1.编译时常量 public static final double PI = 3.14;//命名规范是全部大写,下划线分隔

2.运行时初始化的常量 public final int a = new Random(47).nextInt(20);

final修饰基础类型时表示基础类型变量的值不能变,修饰对象的引用时表示引用本身不能变,不能再指向其他的实例,而引用指向的对象的值是可以改变的(包括数组)。

public class Test20 {	public static void main(String[] args) {		// TODO Auto-generated method stub		final Teacher t = new Teacher();		t.age  = 10;//right		t = new Teacher();//wrong	}}class Teacher{	int age;}
Blank finals

blank finals指的是被声明为final但是没有赋初始值的字段,这些final字段在使用前必须赋值,编译器会保证这一点。这些blank finals必须在各个构造函数中初始化。

综上所述,final字段或者在声明时初始化,或者在各个构造函数中初始化,这样才能保证fianl字段在使用前一定被初始化。

final arguments

当final修饰基础类型参数时,表示在方法中不能改变这个基础类型的值,当修饰对象引用时,表示在方法中不能改变这个引用的值,不能指向新的对象,但是对象的值是可以改变的。

final method

使用final method的原因有两个:

1.子类不能override父类的final method

2.在过去,使用final提示编译器将某个方法当作内联方法处理。在后面的java版本中,虚拟机使用hotspot技术可以自动检测需要使用内联函数的情形并做优化,因此现在不需要使用final提示编译器。

private的方法默认就是final的,虽然在子类中override父类的private方法看上去没错,但实际上已经不是override,因为子类根本看不到父类的perivate方法。

public class Test1 {	public final void go(){		System.out.println("Test1 go");	}}class SubTest1 extends Test1{	public void go(){//Cannot override the final method from Test1			}	public int go(int i){//correct		return i*i;	}}
如上代码所示,虽然不能override,但是可以overload。

我们可以用@Override来表示对父类方法的override,这样如果不是override的话(比如子类对父类private方法的重写)就会报错。

final classes

使用final classes时,表示这个类不能被继承,final类中的方法不管加不加final关键字修饰都是final的,因为不可能被override了,而final类中的属性字段可以是final的也可以不是,这个看需要来定,final的不能改,不是final的可以改变值。

切记不要认为final类的字段也是final的,那就大错特错了。

ArrayList与Vector的区别

ArrayList中的方法没有synchronized关键字修饰,而Vector有,前者效率高些,非线程安全,后者效率低,线程安全。提倡使用前者,由程序员控制同步逻辑。

Hashtable与HashMap的区别

Hashtable中的方法有synchronized关键字修饰,HashMap没有,因此前者效率低,线程安全,后者效率高,非线程安全。HashMap的键和值允许为null,Hashtable不能。提倡使用HashMap替代Hashtable,同步逻辑由程序员控制。

public class Test4 {	public static void main(String args[]){		Hashtable
hTable = new Hashtable
(); HashMap
hMap = new HashMap
(); //hTable.put(null, "1"); //System.out.println(hTable.get(null)); hMap.put(null, "1"); System.out.println(hMap.get(null)); }}
如上代码所示,如果Hashtable键为null,虽然编译不会出错,但是运行时会报空指针错误。而HashMap轻松无压力。可以说,Hashtable写的很差劲,因此要用HashMap取代它。

初始化和类加载

传统语言(C++)程序被加载一次,接着初始化,然后开始执行。

在java中由于每个类的class code在各自的文件中,因此可以在某个类真正需要使用的时候再加载和初始化,即当一个实例被创建,或者类的静态的字段或方法被访问时。

初始化的顺序,就按照静态对象初始化的代码中的顺序,或者静态初始代码块中的顺序。当然,静态的东西只初始化一次。

带继承时候的初始化顺序

class Insect {  private int i = 9;  protected int j;  Insect() {    System.out.println("i = " + i + ", j = " + j);    j = 39;  }  private int p=print(" Insect.p initialized");  private static int x1 =print("static Insect.x1 initialized");  static int print(String s) {    System.out.println(s);    return 47;  }}public class Beetle extends Insect {  private int k = print("Beetle.k initialized");  public Beetle() {    System.out.println("k = " + k);    System.out.println("j = " + j);  }  private static void dd()  { System.out.println("dd ");  }  private static  int x2 =    print("static Beetle.x2 initialized");  public static void main(String[] args) {    System.out.println("Beetle constructor");    Beetle b = new Beetle();      }}
该程序输出:

static Insect.x1 initialized

static Beetle.x2 initialized
Beetle constructor
 Insect.p initialized
i = 9, j = 0
Beetle.k initialized
k = 47
j = 39

当运行Beetle时,访问它的静态的main方法,这个时候Beetle类会被加载,加载完后发现还有父类,因此接着加载父类,直到顶层。

接着父类的static初始化执行,然后是子类的static初始化。

接着执行System.out.println("Beetle constructor");,然后是 Beetle b = new Beetle();。

创建对象时,Beetle的内置类型(包括继承来的)初始化为默认值,引用类型初始化为null。

紧接着父类的非静态成员被初始化,构造函数被调用,然后子类的非静态成员被初始化,接着子类的构造函数被调用。

转载于:https://my.oschina.net/cs7LIl6j/blog/147903

你可能感兴趣的文章
TopCoder SRM 628 DIV 2
查看>>
实验吧_简单的sql注入_1、2、3
查看>>
BZOJ3779重组病毒LCT
查看>>
T-SQL (一)
查看>>
词法分析
查看>>
安装laravel框架
查看>>
Linux 目录结构
查看>>
第二次实验
查看>>
R中,求五数,最小值、下四分位数、中位数、上四分位数、最大值
查看>>
【python-Day3】
查看>>
接上一篇——上海有哪些值得加入的互联网公司
查看>>
VFS相关内容
查看>>
【转载】同步和互斥的POSIX支持(互斥锁,条件变量,自旋锁)
查看>>
+load和+initialize的区别
查看>>
hdu 1319 Prime Cuts
查看>>
Effective_STL 学习笔记(二十四) 当关乎效率时应该在 map::operator[] 和 map-insert 之间仔细选择...
查看>>
Linux课程---7、shell技巧(获取帮助命令)
查看>>
写一个类似淘宝的ios app需要用到哪些技术?
查看>>
#505. 「LibreOJ β Round」ZQC 的游戏
查看>>
#iOS问题记录# UITextview富文本链接,禁止长按事件
查看>>