JAVA基础知识点
这是篇文章会持续更新......
- 在程序设计中经常用到一系列类型,它们需要特殊对待。可以把他们想象成基本类型,之所以特殊对待,是因为new将对象存储在“堆”里,故用new创建一个对象,特别是小的,简单的变量,往往不是很有效。因此对于这些类型,JAVA采取与C/C++相同的方法,也就是说,不用new来创建变量,而是创建一个并非是引用的‘自动’变量,这个变量直接存储‘值’,并置于堆栈中,因此更高效。
2.当创建一个数组对象时,实际上就是创建了一个引用数组,并且每个引用都会被自动初始化为一个特定值,该值拥有自己的关键字null,一旦JAVA看到这个null,就知道这个对象还没有指向某个对象,在使用任何引用前,必须为其指定一个对象,如果试图使用一个还是null的引用,在运行时将会报错,因此常犯的数组错误在JAVA中就可以避免。还可以创建用来存放基本数据类型的数组,同样编译器也能确保这种数组的初始化,因为他会将这种数组所占的内存全部置零。
3.JAVA对象不具备和基本类型一样的生命周期,当用new创建一个JAVA对象时它可以存活于作用域之外,在作用域外引用会消失,但是引用说指向的对象仍继续占据内存空间。
4.通常来说,当创建类时,就是在描述那个类的对象的外观和行为,除非用new创建那个类的对象,否则,实际上并未获得任何对象,执行new来创建对象时,数据存储空间才被分配,其方法才被外界调用。
5.无论创建多少个对象,静态数据都只占用一份存储区域,static不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就回获得基本类型的标准初值,如果它是一个对象引用,那么它的默认初始化值就是null。
6.总结一下对象的创建过程,假设有个名为Dog的类:
- 即使没有显式的使用static关键字,构造器实际上也是静态方法。因此,但首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态域首次被访问时,JAVA解释器必须查找类路径,以定位Dog.class文件。
- 然后载入Dog.class(后面会学到,这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此静态初始化只在Class对象首次加载的时候进行一次。
- 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
- 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,对布尔型和字符型也相同),而引用被设置成了null。
- 执行所有出现于字段定义处的初始化动作。
- 执行构造器,这可能会涉及到很多动作,尤其是设计继承的时候。
- 在JAVA中可以将一个数组赋值给另一个数组,其实真正做的只是复制了一个引用。(重点在于这是引用)
- 由于现在涉及基类和导出类这两个类,而不是只有一个类,所以要试着想象导出类所产生的结果对象,会有点困惑。从外部来看,它就像是一个与基类具有相同接口的新类,或许还会有一些额外的方法和域,但继承并不只是复制基类的接口。当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象是一样的。二者区别在于,后者来自于外部,而基类的子对象被包装在导出类对象内部。
9.“覆盖”只有在某方法时基类的接口的一部分时才会出现。即,必须能将一个对象向上转型为它的基本类型并调用相同的方法。如果某方法是private,它就不是基类的接口的一部分。它仅是一些隐藏与类中的程序代码,只不过是具有相同的名称而已。但如果在导出类中以相同的名称生成一个public,protected或包访问权限方法的话,该方法就不会产生在基类中出现的“仅具有相同名称”的情况。此时你并没有覆盖该方法,仅是生成了一个新的方法,由于private无法触及而且能够有效隐藏。所以除了把它看成是因为它所归属的类的组织结构的原因而存在外,其它任何事物都不需要考虑它。
10.基类的构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类的构造器都能得到调用,这样做是有意义的,因为构造器具有一项特殊任务,检查对象是否被正确的构造。导出类只能访问它自己的成员,不能访问基类中的成员(基类成员通常是private类型)。只有基类的构造器才具有恰当的知识和权限来对自己的元素进行初始化。因此必须令所有构造器都得到调用,否则就不能正确构造完整对象。这正是每个导出类部分都必须调用构造器的原因。在导出类的构造器主体中,如果没有明确指定调用某个基类构造器,它就会“默默”的调用默认构造器,如果不存在默认构造器,编译器就会报错(某个类没有构造器,编译器会自动合成出一个默认构造器)。
11.可以选择在接口中显式的将方法声明为public的,但即使你不这么做,他们也是public的。因此,当要实现一个接口时,在接口中被定义的方法必须被定义为是public的;否则,他们将只能得到默认的包访问权限,这样在方法被继承的过程中,其可访问权限就被降低了,这是Java编译器所不允许的。
12.使用接口的核心原因:为了能够向上转型为多个基类型(以及由此而带来的灵活性)。然而,使用接口的第二个原因却是与使用抽象基类相同;防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。这就带来了一个问题:我们应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口。
13.因为你放入接口中的任何域都自动是static 和final的,所以接口就成为了一种很便捷的用来创建常量组的工具。
14.内部类自动拥有对其外围类所有成员的访问权。这是如何做到的呢?当某个外围类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向外围类对象的应用。然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员。幸运的是,编译器会帮你处理所有的细节,但你现在可以看到,内部类的对象只能在与其外围类的对象相关联的情况下才能被创建(就像你应该看到的,在内部类是非Static类时),构建内部类对象时,需要一个指向其外围类的对象的引用,如果编译器访问不到这个引用就会报错。
15.在拥有外部类对象之前是不可能创建内部类对象的,这是因为内部类对象会暗暗的连接到创建它的外部类对象上。但是,如果你创建的是静态内部类,那么它就不需要对外部类对象的引用。