1.类的继承
class Test {
public Test() { // 构造方法
//...
}
protected void doSomething() { // 成员方法
//...
}
protected Test doIt() { // 方法返回值类型为Test类型
return new Test();
}
}
class Test2 extends Test { // 继承父类
public Test2() { // 构造方法
super(); // 调用父类构造方法
super.doSomething(); // 调用父类成员方法
}
public void doSomethingnew() { // 新增方法
// ...
}
public void doSomething() { // 重写父类方法
// ...
}
protected Test2 doIt() { // 重写父类方法,方法返回值类型为Test2类型
return new Test2();
}
}
当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。原则如下:
1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量
2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承
3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。
(2).子类继承父类的方法
原则:
1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;
2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。
2.Object类
Object类是所有类的父类,是Java类层中的最高层类,实质上Java中任何一个类都是它的子类。当创建一个类时,总是在继承,除非某个类已经指定要从其他类继承,否则它就是从java.lang.Object类继承而来的,如String、Integer等类都是继承于Object类;除此之外自定义的类也都继承于Object类。由于所有类都是Object子类,所以在定义类时,省略了extends Object关键字。
注意:Object类中的getClass()、notify() notifyAll() wait() 等方法不能被重写,因为这些方法被定义为final型。
常见方法:
(1)getclass() 方法
getclass() 方法是Object类定义的方法,它会返回对象执行时的Class实例。
(2)toString() 方法
package hello;
public class Main {
public String toString() { // 重写toString()方法
return "在" + getClass().getName() + "类中重写toString()方法";
}
public static void main(String[] args) {
System.out.println(new Main()); // 打印本类对象
}
}
/*输出:
在hello.Main类中重写toString()方法
*/
(3)equals()方法
package hello;
class V { // 自定义类V
}
public class Main {
public static void main(String[] args) {
String s1 = "123"; // 实例化两个对象,内容相同
String s2 = "123";
System.out.println(s1.equals(s2)); // 使用equals()方法调用
V v1 = new V(); // 实例化两个V类对象
V v2 = new V();
System.out.println(v1.equals(v2)); // 使用equals()方法比较v1与v2对象
}
}
/*输出:
true
false
*/
在自定义的类中用equals() 方法进行比较时,equals() 方法的默认实现是使用“==”运算符比较两个对象的引用地址。
3.对象类型的转换
(1)向上转型
package hello;
class Quadrangle { // 四边形类
public static void draw(Quadrangle q) { // 四边形类中的方法
// ...
}
}
public class Parallelogram extends Quadrangle { // 平行四边形类,继承了四边形类
public static void main(String args[]) {
Parallelogram p = new Parallelogram(); // 实例化平行四边形类对象引用
draw(p); // 调用父类方法 相当于Quadrangle obj=new Parallelogram();
}
}
把子类对象赋值给父类类型的变量,被称为“向上转型”。
四边形类
↑
平行四边形类
(2)向下转型
package hello;
class Quadrangle { // 四边形类
public static void draw(Quadrangle q) { // 四边形类中的方法
// ...
}
}
public class Parallelogram extends Quadrangle { // 平行四边形类,继承了四边形类
public static void main(String args[]) {
draw(new Parallelogram());
// 调用父类方法,向上转型,相当于Quadrangle obj=new Parallelogram();
Quadrangle q = new Parallelogram();
// 将父类对象赋予子类对象,并强制转换为子类型!!!
Parallelogram p = (Parallelogram) q;
}
}
4.使用instanceof操作符判断对象类型
当程序执行向下转型操作时,如果父类对象不是子类对象,就会发生ClassCaseException异常,所以在执行向下执行之前 需要判断父类对象是否为子类对象的实例,这个判断通常使用instanceof操作符来完成。
下面创建Parallelogram类和3个内部类 Quadrangle、Square、Anything。
package hello;
class Quadrangle {
public static void draw(Quadrangle q) {
// ...
}
}
class Square extends Quadrangle {
// ...
}
class Anything {
// ...
}
public class Parallelogram extends Quadrangle {
public static void main(String args[]) {
Quadrangle q = new Quadrangle(); // 实例化父类对象
// 判断父类对象是否为Parallelogram子类的一个实例
if (q instanceof Parallelogram) {
Parallelogram p = (Parallelogram) q; // 向下转型操作
}
// 判断父类对象是否为Parallelogram子类的一个实例
if (q instanceof Square) {
Square s = (Square) q; // 进行向下转型操作
}
// 由于q对象不为Anything类的对象,所以这条语句是错误的
// System.out.println(q instanceof Anything);
}
}
5.方法的重载
package hello;
public class Main {
public static int add(int a, int b) { // 定义一个方法
return a + b;
}
// 定义与第一个方法相同名称、参数类型不同的方法
public static double add(double a, double b) {
return a + b;
}
public static int add(int a) { // 定义与第一个方法参数个数不同的方法
return a;
}
public static int add(int a, double b) { // 定义一个成员方法
return 1;
}
// 这个方法与前一个方法参数次序不同
public static int add(double a, int b) {
return 1;
}
public static void main(String args[]) {
System.out.println("调用add(int,int)方法:" + add(1, 2));
System.out.println("调用add(double,double)方法:" + add(2.1, 3.3));
System.out.println("调用add(int)方法:" + add(1));
}
}
/*
* 输出结果:
* 调用add(int,int)方法:3
* 调用add(double,double)方法:5.4
* 调用add(int)方法:1
*/
6.多态
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
多态存在的三个必要条件:要有继承;要有重写;父类引用指向子类对象。
多态存在的三个必要条件:要有继承;要有重写;父类引用指向子类对象。
package hello;
public class Quadrangle {
// 实例化保存四边形对象的数组对象
private Quadrangle[] qtest = new Quadrangle[6];
private int nextIndex = 0;
public void draw(Quadrangle q) { // 定义draw()方法,参数为四边形对象
if (nextIndex < qtest.length) {
qtest[nextIndex] = q;
System.out.println(nextIndex);
nextIndex++;
}
}
public static void main(String[] args) {
// 实例化两个四边形对象,用于调用draw()方法
Quadrangle q = new Quadrangle();
q.draw(new Square()); // 以正方形对象为参数调用draw()方法
// 以平行四边形对象为参数调用draw()方法
q.draw(new Parallelogramgle());
}
}
class Square extends Quadrangle { // 定义一个正方形类,继承四边形类
public Square() {
System.out.println("正方形");
}
}
// 定义一个平行四边形类,继承四边形类
class Parallelogramgle extends Quadrangle {
public Parallelogramgle() {
System.out.println("平行四边形");
}
}
7.抽象类与接口
抽象类
package hello;
abstract class A {// 定义一个抽象类
public void fun() {// 普通方法
System.out.println("存在方法体的方法");
}
public abstract void print();// 抽象方法,没有方法体,有abstract关键字做修饰
}
// 单继承
class B extends A {// B类是抽象类的子类,是一个普通类
public void print() {// 强制要求覆写
System.out.println("Hello World !");
}
}
public class Main {
public static void main(String[] args) {
A a = new B();// 向上转型
a.print();// 被子类所覆写的过的方法
}
}
/*
* 输出: Hello World !
*/
普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类);
接口
比如说你饿了看见一家店,牌子上写着kfc,当看见kfc这个接口,我们就知道这家店卖鸡腿、汉堡。
接口是抽象类的延伸,java接口必须通过类来实现它的抽象方法,接口中的所有方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化。
public interface drawPic //drawPic是接口名称
{
void draw(); //接口内的方法
}
注意几点:
(1)Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
(2)一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口,一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
接口是抽象类的延伸,java接口必须通过类来实现它的抽象方法,接口中的所有方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化。
public interface drawPic //drawPic是接口名称
{
void draw(); //接口内的方法
}
注意几点:
(1)Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
(2)一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口,一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
interface intf1 { }
interface intf2 extends intf1 { }
(3)当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类
(4)不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
(4)不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
package hello;
interface drawTest { // 定义接口
public void draw(); // 定义方法
}
// 定义平行四边形类,该类继承了四边形类,并实现了drawTest接口
class ParallelogramgleUseInterface extends QuadrangleUseInterface implements
drawTest {
public void draw() { // 由于该类实现了接口,所以需要覆盖draw()方法
System.out.println("平行四边形.draw()");
}
void doAnyThing() { // 覆盖父类方法
// ...
}
}
class SquareUseInterface extends QuadrangleUseInterface implements drawTest {
public void draw() {
System.out.println("正方形.draw()");
}
void doAnyThing() {
// ...
}
}
class AnyThingUseInterface extends QuadrangleUseInterface {
void doAnyThing() {
}
}
public class QuadrangleUseInterface { // 定义四边形类
public void doAnyTthing() {
// ...
}
public static void main(String[] args) {
drawTest[] d = { // 接口也可以进行向上转型操作
new SquareUseInterface(), new ParallelogramgleUseInterface() };
for (int i = 0; i < d.length; i++) {
d[i].draw(); // 调用draw()方法
}
}
}
/*输出结果
正方形.draw()
平行四边形.draw()
*/
Car 的速度运算公式为:A*B/C
Plane 的速度运算公式为:A+B+C。
如果增加第3种交通工具的时候,比如火车(Train)不必修改以前的任何程序,只需要编写新的交通工具的程序。
package hello;
interface Common {
double runTimer(double a, double b, double c);
String getName(); // 获取交通工具的名称
}
class Plane implements Common {
public double runTimer(double a, double b, double c) {
return (a + b + c);
}
public String getName() {
return "Plane";
}
}
class Car implements Common {
public double runTimer(double a, double b, double c) {
return (a * b / c);
}
public String getName() {
return "Car";
}
}
public class Main {
public static void main(String args[]) {
double A = 3;
double B = 5;
double C = 6;
double v, t;
Common d = new Car();
v = d.runTimer(A, B, C);
t = 1000 / v;
System.out.println(d.getName() + "的平均速度: " + v + " km/h");
System.out.println(d.getName() + "的运行时间:" + t + " 小时");
d = new Plane();
v = d.runTimer(10, 30, 40);
t = 1000 / v;
System.out.println(d.getName() + "的平均速度: " + v + " km/h");
System.out.println(d.getName() + "的运行时间:" + t + " 小时");
}
}
/*输出结果
Car的平均速度: 2.5 km/h
Car的运行时间:400.0 小时
Plane的平均速度: 80.0 km/h
Plane的运行时间:12.5 小时
*/