面向对象程序设计的三大基本特征:继承(Inheritence)、封装(Encapsulation)、多态(Polymorphism)。
继承
1. 继承(Inheritence):Java 是单继承的,意味着一个类只能从另一个类继承(被继承的类叫做父类【基类, base class】,继承的类叫做子类),Java中的继承使用 extends 关键字。
2. 当生成子类对象时, Java 默认首先调用父类的不带参数的构造方法,然后执行该构造方法,生成父类的对象。接下来,再去调用子类的构造方法,生成子类的对象。【要想生成子类的对象,首先需要生成父类的对象,没有父类对象就没有子类对象。比如说:没有父亲,就没有孩子】。
3. 关于继承的 3 点:
a) 父类有的,子类也有
b) 父类没有的,子类可以增加
c) 父类有的,子类可以改变
4. 关于继承的注意事项
a) 构造方法不能被继承
b) 方法和属性可以被继承
c) 子类的构造方法隐式地调用父类的不带参数的构造方法
d) 当父类没有不带参数的构造方法时,子类需要使用 super 来显式地调用父类的构造方法,super指的是对父类的引用
e) super 关键字必须是构造方法中的第一行语句。
public class Child extends Parent
{
public Child()
{
super(1);
System.out.println("child");
}
public static void main(String[] args)
{
Child child = new Child();
}
}
class Parent
{
public Parent(int i)
{
System.out.println("parent");
}
/*
public Parent()
{
System.out.println("no args parent");
}
*/
}
5. 在定义一个类的时候,如果没有显式指定该类的父类,那么该类就会继承于 java.lang.Object 类(JDK 提供的一个类, Object类是 Java 中所有类的直接或间接父类)。
封装
1.封装: 类包含了数据与方法,将数据与方法放在一个类中就构成了封装。
public class Test
{
//两个整数相加的方法
public int add(int a, int b)
{
return a + b;
}
//两个整数相减的方法
public int subtract(int a, int b)
{
return a - b;
}
//两个整数相乘的方法
public int multiply(int a, int b)
{
return a * b;
}
//两个整数相除的方法
public int divide(int a, int b)
{
return a / b;
}
//使用void关键字表示方法不返回值
public void output()
{
System.out.println("Hello World");
}
public void method(int a)
{
if(a < 10)
{
return;
}
System.out.println("Welcome to Shengsiyuan!!");
}
//main 方法 是整个Java 程序的入口点, 如果类的定义中没有main 方法, 则程序无法执行
public static void main(String[] args)
{
Test test = new Test();
int x = 8;
int y = 3;
int a = test.add(x, y);
int b = test.subtract(x, y);
int c = test.multiply(x, y);
int d = test.divide(x, y);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
test.output();
int m = 15;
test.method(m);
}
}
多态
1 . 多态(Polymorphism):我们说子类就是父类(玫瑰是花,男人是人),因此多态的意思就是:父类型的引用可以指向子类的对象。
Parent p = newChild();当使用多态方式调用方法时,首先检查父类中是否有sing()方法,如果没有则编译错误;如果有,再去调用子类的 sing()方法。
public class PolyTest
{
public static void main(String[] args)
{
//Parent parent = new Parent();
//parent.sing();
//Child child = new Child();
//child.sing();
Parent p = new Child();
p.sing();
}
}
class Parent
{
/*
public void sing()
{
System.out.println("parent is singing");
}
*/
}
class Child extends Parent
{
public void sing()
{
System.out.println("child is singing");
}
}
2. 类型转换:一共有两种类型的强制类型转换:
a) 向上类型转换(upcast) :比如说将 Cat 类型转换为 Animal 类型,即将子类型转换为父类型。对于向上类型转换,不需要显式指定。
b) 向下类型转换(downcast) :比如将 Animal 类型转换为 Cat 类型。即将父类型 转换为子类型。对于向下类型转换,必须要显式指定(必须要使用强制类型转换) 。
public class PolyTest2
{
public static void main(String[] args)
{
/*
Animal animal = new Cat();
Animal animal2 = new Animal();
animal2 = animal;
animal2.sing();
*/
/*
Animal animal = new Cat();
Animal animal2 = new Animal();
animal = animal2;
animal.sing();
*/
/*
Cat cat = new Cat();
Animal animal = cat;
animal.sing();
*/
/*
Animal animal = new Animal();
Cat cat = (Cat)animal;
*/
//向上类型转换
Cat cat = new Cat();
Animal animal = cat;
animal.sing();
//向下类型转换
Animal a = new Cat();
Cat c = (Cat)a;
c.sing();
}
}
class Animal
{
public void sing()
{
System.out.println("animal is singing");
}
}
class Dog extends Animal
{
public void sing()
{
System.out.println("dog is singing");
}
}
class Cat extends Animal
{
public void sing()
{
System.out.println("cat is singing");
}
}
c)可以使用Instanceof判断某个对象是否是某个类的实例。返回值boolean
public class InstanceofTest
{
public static void main(String[] args)
{
People people = new Man();
System.out.println(people instanceof People);
}
}
class People
{
}
class Man extends People
{
}
3.方法重载(Overload)和方法重写(Override)
a)方法重载:(一个类)表示两个或多个方法名字相同,但方法参数不同。方法参数不同有两层含义:
1)参数个数不同。
2)参数类型不同。 注意:方法的返回值对重载没有任何影响。
b) 构造方法重载:只需看参数即可。如果想在一个构造方法中调用另外一个构造方法, 那么可以使用 this()的方式调用, this()括号中的参数表示目标构造方法的 参数。this()必须要作为构造方法的第一条语句,换句话说,this()之前不能有任何可执行的代码。
public class ConstructorOverload
{
public ConstructorOverload()
{
this(3);
System.out.println("test");
}
public ConstructorOverload(int i)
{
System.out.println(++i);
}
public static void main(String[] args)
{
ConstructorOverload col = new ConstructorOverload();
}
}
c) 方法重写(Override) :(两个或两个以上)又叫做覆写,子类与父类的方法返回类型一样、方法名称一样,参数一样,这样我们说子类与父类的方法构成了 重写关系。
抽象类和接口
1. 抽象类(abstract class) :使用了 abstract 关键字所修饰的 类叫做抽象类。抽象类无法实例化,也就是说,不能 new 出来一个抽象类的对象(实例) 。
2. 抽象方法(abstract method) :使用 abstract 关键字所修饰的方法叫做抽象方法。 抽象方法需要定义在抽象类中。相对于抽象方法,之前所定义的方法叫做具体方法(有声明,有实现) 。
3. 如果一个类包含了抽象方法,那么这个类一定是抽象类。
4. 如果某个类是抽象类,那么该类可以包含具体方法(有声明、有实现) 。
5. 如果一个类中包含了抽象方法,那么这个类一定要声明成 abstract class,也就是说,该类一定是抽象类;反之,如果某个类是抽象类,那么该类既可以包含抽象方法,也可以包含具体方法。
6. 无论何种情况,只要一个类是抽象类,那么这个类就无法实例化。
7. 在子类继承父类(父类是个抽象类)的情况下,那么该子类必须要实现父类中所定义的所有抽象方法;否则,该子类需要声明成一个 abstract class。
public class Test2
{
public static void main(String[] args)
{
Shape shape = new Triangle(10,6);
int area = shape.computeArea();
System.out.println("triangle:" + area);
shape = new Rectangle(10, 10);
area = shape.computeArea();
System.out.println("rectangle:" + area);
}
}
abstract class Shape
{
public abstract int computeArea();//计算形状面积
}
class Triangle extends Shape
{
int width;
int height;
public Triangle(int width, int height)
{
this.width = width;
this.height = height;
}
public int computeArea()
{
return (width * height) / 2;
}
}
class Rectangle extends Shape
{
int width;
int height;
public Rectangle(int width, int height)
{
this.width = width;
this.height = height;
}
public int computeArea()
{
return this.width * this.height;
}
}
8. 接口(interface) :接口的地位等同于 class, 接口中的所有方法都是抽象方法。在声明接口中的方法时,可以使用 abstract 关键字,也可以不使用。通常情况下,都会省略掉 abstract 关键字。
9. 可以将接口看作是特殊的抽象类(抽象类中可以有具体方法,也可以有抽象方法,而接口中只能有抽象方法,不能有具体方法) 。
10. 类可以 实现接口。实现使用关键字 implements 表示,代表了某个类实现了某个接口。
11. 一个类实现了某个接口,那么该类必须要实现接口中声明的所有方法。如果该类是个抽象类,那么就无需实现接口中的方法了。
12. Java 是单继承的,也就是说某个类只能有唯一一个父类;一个类可以实现多个接口,多个接口之间使用逗号分隔。
public class Test3
{
public static void main(String[] args)
{
MyClass myClass = new MyClass();
myClass.output();
myClass.output2();
myClass.output3();
}
}
interface MyInterface
{
public void output();
}
interface MyInterface2
{
public void output2();
}
class MyParent
{
public void output3()
{
System.out.println("output3");
}
}
class MyClass extends MyParent implements MyInterface, MyInterface2
{
public void output()
{
System.out.println("output");
}
public void output2()
{
System.out.println("output2");
}
}
13. 注意:一个类不能既是 final,又是 abstract 的。因为 abstract 的主要目的是定义一种约定,让子类去实现这种约定,而 final 表示该类不能被继承,这样 abstract 希望该类可以被继承而 final 明确说明该类不能被继承,两者矛盾。因此一个类不能既是 final 的,又是 abstract 的。