1. Java源文件的规则与编译方式:
- 如果一个.java文件中含有多个类,则只有其中一个类可以含有main()方法,并且这个java文件名要与这个类一致。并且,这个文件中也只能有一个public类,即main所在的类。
- 如果一个java文件含有一个类,但是这些类之间相互调用,则有两种方式可以进行编译:第一种:如果这些类有相同的前缀(例如一个叫Employee,一个叫EmployeeTest,其中EmployeeTest调用了Employee),可以通过javac Employee*.java进行编译。第二种方式是使用javac EmployeeTest.java进行编译,此时,java编译器会自动识别EmployeeTest调用的类,如果发现有没有编译的,就会自动编译那个类。
- 无论写在多个文件中还是一个文件中,使用javac命令编译完成后,有多少个类,就会产生多少个同名的.class文件。
2. 静态方法
使用static修饰符,可以对类,类中的变量或常量,类中的方法分别进行修饰。
- 静态量:使用static修饰变量或者常量,这个量就变为静态的。带来的影响是:不管创建多少个这个类的实例,内存中都只有一个静态量。也就是说,这个类的每个成员共享这一个静态量。
- 静态方法:使用static修饰方法。带来的影响是:无法使用这个类的对象来调用这个方法。举个例子:Math类中有静态方法pow,pow的调用不是先创建Math类的一个对象,然后使用这个对象来调用pow,而是直接使用Math.pow()。当然,类的对象也可以调用静态方法,但是没有使用类名直观。这里需要强调的是,由于静态方法不需要创建对象就可以使用,所以静态方法不能够访问类的实例域。这也是说的通的,因为在没有创建对象的情况下,显然也没有实例被创建,所以静态方法无法对实例进行访问。但是,静态方法可以访问上面提到的静态量。
3. 方法参数
java中的函数参数,都是值传递。没有引用传递。由于对象的名字类似于指针,所以函数中传递一个对象,实际上相当于复制了一个指向这个对象的指针,然后这个指针在函数结束之后会被回收。
4. 构造
- 类中的方法可以重载,要求是参数需要不同。不可以重载两个参数相同但是返回值不同的方法。
- 类如果没有构造函数,则new一个新的对象的时候,或默认赋值(0,false,null)。但只要定义了一个含有参数的构造函数,在使用无参数的默认构造时就会报错。解决办法是自行定义一个没有参数的默认构造函数。
- 可以在类中定义量时,就赋一个初值。java的创建对象顺序是:先赋值,再调用构造函数。
- java的构造函数中,由于可以重载,因此在一个构造函数中可以使用this调用其他构造函数。
5. 超类与子类
子类继承了超类的量与方法。
- 子类可以使用super的方式初始化继承自超类的量。因为子类本身不能修改和初始化超类,所以需要使用super,而super会调用超类中合适的构造函数。
- 子类可以用与超类方法一样的名字命名自己的方法,这种情况称为覆盖。注意:覆盖时很可能调用超类的同名方法,例如覆盖getBonus()这个方法,则不能在子类的实现中直接使用,因为这意味着递归。要使用super.getBonus()才能够调用超类的这个方法。
- 超类变量可以引用子类的值,反之不可以。因此可以用超类定义一个数组,但数组中的变量可以有超类和子类。注意:此时,不可以用索引的方式调用子类方法,例如:Manager是Employee的子类,有一个新的方法getBonus(),有一个Employee数组e[5],其中第一位e[0]是Manager,后面是Employee,此时,不可以用e[0].getBonus()调用Manager的特有方法。但是,如果调用一个同名的方法,例如getSalary(),来遍历整个数组,编译器会自动调用各自的方法,也就是说第一位使用Manager的方法,后面使用Employee的方法。遍历过程中,一个变量(例如叫emp),可以指定Employee类的对象和Manager类的对象,这称为多态。而编译器根据变量指向的对象的类型,动态选择调用的哪个类的方法,称为动态链接。
- 强制类型转换:只有在继承层次中才可以进行强制类型转换。子类可以转换为超类。反之不可。但是,在一个包含子类和超类对象的数组中,由于数组一定是超类类型的,如果想要调用其中子类对象的子类方法,可以对这个对象进行强制类型转换。否则,将无法调用其中的子类方法。为了避免误操作,需要检测instanceof()。
- 抽象类:含有抽象方法的类必须声明为抽象类。不含有的也能声明为抽象类。抽象类不能创建该类型的实例,但是可以引用子类对象。