1.定义类:
对一个类定义而言,可以包含三种最常见的成员:构造器、成员变量和方法,三种成员都可以定义零个或多个,如果三种成员都只定义零个,就是定义了一个空类,这没有太大的实际意义。
类里各成员之间的定义顺序没有任何影响,各成员之间可以相互调用,但需要指出的是,static修饰的成员不能访问没有static修饰的成员。
成员变量用于定义该类或该类的实例所包含的状态数据,方法则用于定义该类或该类的实例的行为特征或者功能实现。构造器用于构造该类的实例,Java语言通过new关键字来调用构造器,从而返回该类的实例。
构造器是一个类创建对象的根本途径,如果一个类没有构造器,这个类通常无法创建实例。因此,Java语言提供了一个功能:如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器。一旦程序员为一个类提供了构造器,系统将不再为该类提供构造器。
成员变量:
方法:
static是一个特殊的关键字,它可用于修饰方法、成员变量等成员。static修饰的成员表明它属于这个类本身,而不属于该类的单个实例,因为通常把 static修饰的成员变量和方法也称为类变量、类方法。不使用static修饰的普通方法、成员变量则属于该类的单个实例,而不属于该类。因为通常把不使用static修饰的成员变量和方法也称为实例变量、实例方法。
由于static的英文直译就是静态的意思,因此有时也把 static修饰的成员变量和方法称为静态变量和静态方法,把不使用static修饰的成员变量和方法称为非静态变量和非静态方法。静态成员不能直接访问非静态成员。构造器:
值得指出的是,构造器既不能定义返回值类型,也不能使用void声明构造器没有返回值。如果为构造器定义了返回值类型,或使用void声明构造器没有返回值,编译时不会出错,但Java会把这个所谓的构造器当成方法来处理——它就不再是构造器。
2.对象的this引用
Java提供了一个this关键字,this关键字总是指向调用该方法的对象。根据 this出现位置的不同,this 作为对象的默认引用有两种情形。
this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或实例变量。
在现实世界里,对象的一个方法依赖于另一个方法的情形如此常见:例如,吃饭方法依赖于拿筷子方法,写程序方法依赖于敲键盘方法,这种依赖都是同一个对象两个方法之间的依赖。因此,Java允许对象的一个成员直接调用另一个成员,可以省略this前缀。也就是说,将上面的run()方法改为如下形式也完全正确。
对于static修饰的方法而言,则可以使用类来直接调用该方法,如果在 static修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象。所以,static修饰的方法中不能使用this引用。由于 static修饰的方法不能使用this引用,所以 static修饰的方法不能访问不使用static修饰的普通成员,因此Java语法规定:静态成员不能直接访问非静态成员。
3.方法的参数传递机制
从上面运行结果来看,swap()方法里a和 b的值是9、6,交换结束后,变量a和 b的值依然是6、9。从这个运行结果可以看出,main()方法里的变量a和b,并不是swap()方法里的a和b。正如前面讲的,swap()方法的a和 b只是main()方法里变量a和 b的复制品。下面通过示意图来说明上面程序的执行过程。Java程序总是从main()方法开始执行,main()方法开始定义了a、b两个局部变量,两个变量在内存中的存储示意图如图5.3所示。
4.形参个数可变的方法:
从JDK 1.5之后,Java允许定义形参个数可变的参数,从而允许为方法指定数量不确定的形参。如果在定义方法时,在最后一个形参的类型后增加三点(...),则表明该形参可以接受多个参数值,多个参数值被当成数组传入。下面程序定义了一个形参个数可变的方法。
5.关于访问修饰符的使用,存在如下几条基本原则:
- 类里的绝大部分成员变量都应该使用private修饰,只有一些static修饰的、类似全局变量的成员变量,才可能考虑使用public修饰。除此之外,有些方法只用于辅助实现该类的其他方法,这些方法被称为工具方法,工具方法也应该使用private修饰。
- 如果某个类主要用做其他类的父类,该类里包含的大部分方法可能仅希望被其子类重写,而不想被外界直接调用,则应该使用protected修饰这些方法。
- 希望暴露出来给其他类自由调用的方法应该使用public修饰。因此,类的构造器通过使用public修饰,从而允许在其他地方创建该类的实例。因为外部类通常都希望被其他类自由使用,所以大部分外部类都使用public修饰。
6.import
通过使用import 语句可以简化编程。但import 语句并不是必需的,只要坚持在类里使用其他类的全名,则可以无须使用import语句。
遇到不同包重名
JDK 1.5以后更是增加了一种静态导入的语法,它用于导入指定类的某个静态成员变量、方法或全部的静态成员变量、方法。
静态导入使用import static语句,静态导入也有两种语法,分别用于导入指定类的单个静态成员变量、方法和全部静态成员变量、方法,其中导入指定类的单个静态成员变量、方法的语法格式如下:上面语法导入package.subpackage.….ClassName类中名为fieldName的静态成员变量或者名为methodName的静态方法。例如,可以使用import static java.lang.System.out;语句来导入java.lang.System类的out静态成员变量。
所谓静态成员变量、静态方法其实就是前面介绍的类变量、类方法,它们都需要使用static修饰,,而static在很多地方都被翻译为静态,因此 import static也就被翻译成了“静态导入”。其实完全可以抛开这个翻译,用一句话来归纳 import和 import static 的作用:使用import可以省略写包名;而使用importstatic 则可以连类名都省略。
下面程序使用 import static语句来导入java.lang.System类下的全部静态成员变量,从而可以将程序简化成如下形式。
Java源文件的大体结构:
7.Java的常用包
Java的核心类都放在java包以及其子包下,Java扩展的许多类都放在javax包以及其子包下。这些实用类也就是前面所说的API(应用程序接口),Oracle按这些类的功能分别放在不同的包下。下面几个包是Java语言中的常用包。
- java.lang:这个包下包含了Java语言的核心类,如 String、Math、System和Thread类等,使用这个包下的类无须使用import语句导入,系统会自动导入这个包下的所有类。
- java.util:这个包下包含了Java的大量工具类/接口和集合框架类/接口,例如Arrays和List、Set等。
- java.net:这个包下包含了一些Java 网络编程相关的类/接口。
- java.io:这个包下包含了一些Java输入/输出编程相关的类/接口。
- java.text:这个包下包含了一些Java格式化相关的类。
- java.sql:这个包下包含了Java进行JDBC 数据库编程的相关类/接口。
- java.awt:这个包下包含了抽象窗口工具集(Abstract Window Toolkits)的相关类/接口,这些类主要用于构建图形用户界面((GUI)程序。
- java.swing:这个包下包含了Swing图形用户界面编程的相关类/接口,这些类可用于构建平台无关的GUI程序。
8.重写父类的方法
方法的重写要遵循“两同两小一大”规则
- “两同”即方法名相同、形参列表相同;
- “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
- “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等。
尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。不然将会引发编译错误。
如果父类方法具有 private访问权限,则该方法对其子类是隐藏的,因此其子类无法访问该方法,也就是无法重写该方法。如果子类中定义了一个与父类 private方法具有相同的方法名、相同的形参列表、相同的返回值类型的方法,依然不是重写,只是在子类中重新定义了一个新方法。例如,下面代码是完全正确的。
方法重载和方法重写在英语中分别是overload和 override,经常看到有些初学者或一些低水平的公司喜欢询问重载和重写的区别?其实把重载和重写放在一起比较本身没有太大的意义,因为重载主要发生在同一个类的多个同名方法之间,而重写发生在子类和父类的同名方法之间。它们之间的联系很少,除二者都是发生在方法之间,并要求方法名相同之外,没有太大的相似之处。当然,父类方法和子类方法之间也可能发生重载,因为子类会获得父类方法,如果子类定义了一个与父类方法有相同的方法名,但参数列表不同的方法,就会形成父类方法和子类方法的重载。
9. super限定
super是Java提供的一个关键字, super用于限定该对象调用它从父类继承得到的实例变量或方法。正如 this 不能出现在static修饰的方法中一样,super也不能出现在static修饰的方法中。static修饰的方法是属于类的,该方法的调用者可能是一个类,而不是对象,因而 super限定也就失去了意义。
如果在构造器中使用super,则 super用于限定该构造器初始化的是该对象从父类继承得到的实例变量,而不是该类自己定义的实例变量。
查询顺序
(1)查找该方法中是否有名为a的局部变量。
(2)查找当前类中是否包含名为a的成员变量。
(3)查找a的直接父类中是否包含名为a的成员变量,依次上溯a的所有父类,直到java.lang.Object类,如果最终不能找到名为a的成员变量,则系统出现编译错误。
如果被覆盖的是类变量,在子类的方法中则可以通过父类名作为调用者来访问被覆盖的类变量。
散装知识点:
- 使用static修饰的方法属于这个类本身,使用static修饰的方法既可以使用类作为调用者来调用,也可以使用对象作为调用者来调用。但值得指出的是,因为使用static修饰的方法还是属于这个类的,因此使用该类的任何对象来调用这个方法时将会得到相同的执行结果,这是由于底层依然是使用这些实例所属的类作为调用者。
- 值得指出的是,Java的子类不能获得父类的构造器。
- Java语言摒弃了C++中难以理解的多继承特征,即每个类最多只有一个直接父类。例如下面代码将会引起编译错误。
很多书在介绍Java 的单继承时,可能会说Java类只能有一个父类,严格来讲,这种说法是错误的,应该换成如下说法:Java类只能有一个直接父类,实际上,Java类可以有无限多个间接父类。例如:
上面的类定义中 Fruit是Apple类的父类,Plant类也是Apple类的父类。区别是Fruit是Apple的直接父类,而Plant则是Apple类的间接父类。