Java面向对象
1.面向对象
主要是对现实世界事物的抽象。
2.类
类是一个模板,用于描述一类事物对象的特征状态和行为。比如狗,描述所有狗类的状态和行为。
类有内部类,匿名内部类。
3.对象
对象是类的一个实例,在现实世界是看得见摸得着的,特征状态和行为。比如二哈是一个具体的对象,有颜色、名字等状态;有摇尾巴、叫等行为。
4.属性
属性就是对象的特征状态
5.方法
方法就是对象的行为。
6.构造方法
1.作用
用于创建对象,完成对象创建的初始化。在Java中,使用关键字new来创建一个新的对象。创建对象需要以下三步:
1.声明 声明一个对象,包括对象名称和对象类型。 2.实例化 使用关键字new 来创建一个对象。 3.初始化 使用new创建对象时,会调用构造方法初始化对象。 2.语法
不能定义返回类型,方法名必须跟类名一致。
3.注意事项
1. 如果没有显式的为类定义构造方法,Java编译器会为该类提供一个默认的构造方法;
2.如果显式的为一个类提供一个或多个有参构造方法,系统则不会提供默认的无参构造方法,因此,当父类中定义了一个或多个有参数构造方法时,应显式的写一个无参数的构造方法,以防子类省略super关键字时出现错误。 3.构造方法不能定义返回类型,方法名要跟类名一致。
7.访问实例变量和方法
通过已创建的对象来访问成员变量和成员方法。
8.继承
1.继承的概念
继承就是子类继承父类的特征状态和行为,使得子类对象(实例)具有父类的特征状态和方法。所以,继承需要符合的关系就是:is-a关系,父类更通用,子类更具体。
继承描述如下图所示:
2.注意事项
Java不支持多继承,但是支持多重继承。如下图所示:
3.继承的特性
1.子类继承父类后,具有且可见父类的非private属性和方法,具有且不可见父类的private属性和方法 2.子类可以拥有自己独特的属性和方法,即子类可以对父类进行扩展。 3.子类可以重写父类的方法 4.继承提高了类与类之间的耦合性(即继承的缺点,耦合度高会造成代码之间的联系越紧密,代码的独立性越差)。 5.继承会减少所有子类中重复性代码,维护性更高,代码更加简洁。 4.继承关键字
继承可以使用extends和implements这两个关键字来实现继承,而且所有的类都是继承自java.lang.object。当一个类没有继承的两个关键字,则会默认继承object(这个类在java.lang包中,不需要import)祖先类。
- extends关键字
只能单一继承,一个类只能拥有一个父类。
- implements关键字
用于继承接口,可同时继承多个接口(接口与接口之间采用逗号进行分割)。
public interface A { public void eat(); public void sleep(); } public interface B { public void show(); } //继承多个接口 public class C implements A,B { }
5.final关键字
final关键字声明类可以把类定义位不能被继承的,即最终类;或者由于修饰方法,则该方法不能被子类重写。
9.子类
1.构造子类对象
1. 构造子类对象时,会先构造Object,然后构造其所有的父类对象,最后构造其子类对象。 2.子类不会继承父类的构造方法,会继承父类的私有属性和方法,但私有属性和方法对子类不可见。 3.如果子类有构造方法,那么创建子类的对象时,先执行父类的构造方法,再执行子类的构造方法。 4.如果子类没有构造方法,则它默认调用父类无参的构造方法,如果父类中没有无参数的构造方法,则将产生错误。 5.按继承关系,构造方法是从顶向下进行调用的。定义子类的一个对象时,会先调用子类的构造函数,然后在调用父类的构造函数,如果父类函数足够多的话,会一直调用到最终的父类构造函数,函数调用时会使用栈空间,所以按照入栈的顺序,最先进入的是子类的构造函数,然后才是邻近的父类构造函数,最后再栈顶的是最终的父类构造函数,构造函数执行是则按照从栈顶到栈底的顺序依次执行. 2.super关键字
super有两种形式:super和super()
- super
用于调用父类的成员变量名和方法。使用super首先到直接父类查找匹配,如果未找到,再逐层向上到祖先类查找。
//祖先类 public class Root { public void test() { System.out.println("root test "); } } //父类 public class Parent extends Root { } //子类 public class Child extends Parent{ @Override public void test() { System.out.println("child test "); } public void sum() { super.test(); } } //测试类 public class Test { public static void main(String[] args) { Child child = new Child(); child.sum(); } } 输出结果为:root test
格式如下:
super.<父类的成员变量>; super.<父类的成员方法名>;
- super()
通过super();来调用父类中定义的构造方法。格式如下:
super();或者super(参数);
1. super关键字是指向父类的引用。可以通过super关键字来实现对父类成员的方法,用来引用当前对象的父类。 2.如果子类的构造方法没有显式的调用父类的构造方法,那么编译器会自动为构造方法添加一个默认的super()方法调用。 3.使用super()时,如果父类没有无参构造方法时,编译器就会报错。 4.super()语句必须在构造方法的第一行。 3.this关键字
指向自己的引用。
重写
1.重写概念
重写就是子类对父类的允许访问的方法的实现过程进行重新编写(重写只针对方法),返回值和形参都不能改变(即外壳不变,核心重写)。重写的好处就是子类可以定义自己独特的行为。如下所示:
//动物类 class Animal{ public void move(){ System.out.println("动物可以移动"); } } //狗类 class Dog extends Animal{ public void move(){ System.out.println("狗可以跑和走"); } } //测试类 public class TestDog{ public static void main(String args[]){ Animal a = new Animal(); // Animal 对象 Animal b = new Dog(); // Dog 对象 a.move();// 执行 Animal 类的方法 b.move();//执行 Dog 类的方法 } } 运行结果: 动物可以移动 狗可以跑和走
在上面的例子中可以看到,尽管b属于Animal类型,但是它运行的是Dog类的move方法。这是由于在编译阶段,只是检查参数的引用类型。然而在运行时,Java虚拟机(JVM)指定对象的类型并且运行该对象的方法。因此在上面的例子中,之所以能编译成功,是因为Animal类中存在move方法,然而运行时,运行的是特定对象的方法。
2.重写的规则
1.参数列表必须完全与被重写方法的相同。 2.返回类型与被重写方法返回类型可以不相同,但是必须是父类返回值的派生类。 3.访问权限不能比父类中被重写的方法的访问权限更低。 4.父类的成员方法只能被它的子类重写。 5.声明为final的方法不能被重写。 6.声明为static的方法不能被重写,但是能够被再次声明。 7.子类和父类在同一个包中,那么子类可以重写父类的所有方法,除了声明为private和final方法。 8.子类和父类不再同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。 9.构造方法不能被重写。 10.如果不能继承一个方法,则不能重写这个方法。 3.注意事项
- 重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的一次。例如,父类一个方法声明了一个检查异常IOException,但是在重写这个方法时不能抛出Exception异常,因为Exception是IOException的父类。
- 子类在实例化后调用重写方法时,首先会调用子类的重写方法,如果子类没有重写该方法,则会向上调用父类的该方法,如果父类没有重写这个方法,则会再去调用上一级的该方法,直到找到该方法。如下所示:
//祖先类 public class Root { public void test() { System.out.println("root test "); } } //父类 public class Parent extends Root { @Override public void test() { System.out.println("parent test "); } } //子类 public class Child extends Parent{ @Override public void test() { System.out.println("child test "); } } //测试类 public class Test { public static void main(String[] args) { Child child = new Child(); child.test(); } } 输出结果为:child test
有如下测试:
1.如果子类没有重写test方法,则输出结果为:parent test 2.如果子类重写了test方法,但是方法里面没有任何实现,则输出结果为:什么都不输出 3.如果Child和Parent都没有重写test方法,则输出结果为:root test
重载
1.重载概念
重载就是在一个类里面,方法名称相同,而参数不同,返回类型可以相同也可以不相同。如下所示:
2.重载规则
1.被重载的方法必须改变参数列表(参数个数或参数类型不一样)。 2.被重载的方法可以改变返回类型。 3.被重载的方法可以改变访问修饰符。 4.被重载的方法可以声明新的或者更广的检查异常。 5.方法能够在同一个类中或者在一个子类中被重载。 6.无法以返回值类型作为重载函数的区分标准。 3.重载与重写的区别
区别点 重载方法 重写方法 参数列表 必须修改 不能修改 返回类型 必须修改 不能修改 异常 可以修改 可以减少或者删除,不能抛出新的或者更广的异常 访问 可以修改 不能做更严格的限制(可以降低限制) 如下图所示:
4.总结
方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
多态
1.多态概念
多态是一个行为具有多个不同表现形式或者形态的能力。多态就是一个接口,使用不同的实例而执行不同的操作。如下图所示:
2.多态的优点
1.消除类型之间的耦合关系 2.可替换性 3.可扩展性 4.接口性 5.灵活性 6.简化性 7.屏蔽不同子类之间的差异性。 3.多态存在的必要条件
- 继承
- 重写
- 父类引用指向子类对象
比如:Parent p = new Child();
4.注意事项
使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,则再去调用子类的同名方法。即编译看父类,运行看子类。
5.多态的实现方式
- 重写
- 接口
- 抽象类与抽象方法
抽象类
1.abstract关键字
Java中使用abstract关键字来定义抽象类。
参考资料:菜鸟教程 https://www.runoob.com