- 面向对象的三大特征
- 封装
- 继承
- 多态
封装
-
将类的某些信息隐藏在类内部,不允许外部程序直接访问,
而是通过该类提供的方法来实现对隐藏信息的操作和访问 。
-
封装的具体表现:使用不同的访问权限
public class Demo{
private String name;
public String getName (){
return name;
}
public void setName(String name){
this.name = name;
}
}
- 可以通过一个特定的方法来对隐藏信息进行访问,便于控制
public class Animal{
private static String name="monkey";
private Animal(){
}
public static void getName(/*这里可以添加参数*/){//可以用静态方法来访问私有的信息,因为静态方法随类加载而加载
//这里可以添加一些条件来限制访问
System.out.println(name);
//也可以改变返回值
}
}
class Test{
public static void main(String[] args) {
Animal.getName();//用类名调用静态方法
}
}
继承
-
继承是面向对象程序设计不可缺少的设计思想,是实现代码可重用的根基,是提高代码可扩展性的主要途径。
-
继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,
并能扩展新的能力。 (子类继承父类,实现代码的重复利用,扩展性好)
-
在JAVA中使用extends关键字来表示继承关系。
-
JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个
直接父类
-
继承之后子类可以调用父类的所有非私有属性和非私有方法
-
什么是什么的关系:
- 猫是动物
- 宝马是车
-
除了继承父类的功能之外,还可以扩展自己的功能
-
-
继承的形式:
- [访问权限修饰符][修饰符] 子类名 extends 父类名{子类体}
public class Animal{
public void eat(){}
}
public class Dog extends Animal{
public void play(){}
}
//子类对象可以直接调用父类的方法,强调复用性
Dog dog = new Dog ();
dog.eat();
- 继承具有传递性
比如:哮天犬继承狗继承动物,哮天犬就具有了狗和动物的非私有属性和方法
-
当一个类没有显示继承某个类,那么这个类默认继承Object类,Object是所有类的基类
-
继承中的构造方法
- 在创建子类对象后,调用构造方法时,从上到下的调用,先初始化父类的信息
- 使用super()在子类构造方法的第一行默认调用父类无参构造方法
- 若父类有有参构造方法,则需要在子类构造方法第一行使用super(参数列表)调用父类有参构造方法
-
super关键字 使用super关键字访问父类成员
- 用super.成员变量名来引用父类成员变量
- 用super.方法名(参数列表)访问父类的方法。
- 用super()访问父类无参构造方法
- 用super(参数列表)访问父类有参构造方法
-
误区: 不要把super误认为是父类对象.在创建子类对象时,
不会创建父类对象.
只会将父类中的信息加载到子类对象中存储.
-
重写(OverRide)
- 应用场景:当父类的方法实现不能满足子类需求时,可以对方法进行重写
- 在子类中可以根据需要对从基类中继承来的方法进行重写。
- 方法重写规则
- 方法名相同、参数列表相同;
- 返回值类型相同;
- 访问权限不能小于父类权限;(若父类是默认的,则子类重写方法权限为默认或protected的或者public)
- 注意:构造方法,静态方法不能重写,成员变量不存在重写
public class Person{
private String name;
private int age;
private char sex;
public Person(){//人类无参构造方法
System.out.println("人类无参构造方法");
}
public Person(String name,int age,char sex){
super();
this.name=name;
this.age=age;
this.sex=sex;
System.out.println("人类有参构造方法");
}
public void sleep(){
System.out.println("人类睡觉");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
public class Chinese extends Person{//中国人类继承人类类
static String country="中国";
public Chinese(){
super();//默认访问父类无参构造方法
System.out.println("中国人无参构造方法");
}
public Chinese(String name,int age,char sex){
super(name,age,sex);//访问父类有参构造犯法
System.out.println("中国人有参构造方法");
}
public void festival(){
System.out.println("中国人过春节");
sleep();
}
@Override//这是java中提供的一个注解标签(是一种方法重写的标记)
//添加此标记表示此方法是从父类重写过来的,会对其语法进行验证
public void sleep() {//重写父类的sleep()
System.out.println("中国人躺着睡觉");
}
public void getCountry(){
System.out.println("国籍:"+country);
}
}
public class Student extends Chinese {//学生继承中国人
static String school="理工大学";
public Student(){
//默认访问父类无参构造方法
System.out.println("学生无参构造方法");
}
public Student(String name,int age,char sex){
super(name,age,sex);//访问父类有参构造犯法
System.out.println("学生有参构造方法");
}
public void getSchool(){
System.out.println("学校:"+school);
}
public void learn(){
System.out.println("学生学习");
super.sleep();
}
}
public class Test {//测试类
public static void main(String[] args) {
Student wh = new Student("zs",22,'男');//创建一个学生对象
System.out.println(wh.getAge());//输出年龄
System.out.println();
System.out.println(wh.getName());//输出姓名
wh.getCountry();//输出国籍
wh.festival();
wh.sleep();
System.out.println();
System.out.println(wh.getSex());//输出性别
wh.getSchool();
wh.learn();
}
}
抽象类:
-
抽象方法
- 抽象方法是一种特殊的方法:它只有声明,而没有具体的实现
- 抽象方法必须用abstract关键字进行修饰.
-
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象
类。
-
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方
法和构造方法。
-
用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必
须定义成抽象类。
-
特点:
- 抽象类不能被实例化,但可以有构造方法,因为抽象类中含有无具体实现的方法, 所以不能用抽象类创建对象。
- 抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实 现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一 样。否则,该类也必须声明为抽象类。
-
使用关键字abstract定义抽象类,一般语法:
-
[访问权限] abstract class 类名 { 成员列表 } public abstract class Shapes { public abstract void draw(); } public abstract class Shapes { public void draw(){ //具体代码 } }
-
-
抽象类,抽象方法,在软件开发过程中都是设计层面的概念。也就是说,
设计人员会设计出抽象类,抽象方法,程序员都是来继承这些抽象类并
覆盖抽象方法,实现具体功能。
多态:
-
同一种事物,在不同时刻表现不同的状态
-
多态存在的三个必要条件
- 要有继承(包括接口的实现)(前提条件)
- 要有重写(前提条件)
- 父类引用指向子类对象
-
当编译期类型是父类,运行期类型是子类时,被称为父类引用指向子类对象
-
class Animal{ …… } class Cat extends Animal{ …… } class Dog extends Animal { …… } Animal x = new Cat() //Animal 的引用指向Cat的对象
-
public abstract class Animal {//抽象动物类 int num = 3; public Animal(){ //无参构造方法 } public abstract void eat();//抽象方法无方法体 } class Cat extends Animal{//猫继承动物类 @Override public void eat() {//在子类中重写eat方法 System.out.println("猫吃东西"); } } class Dog extends Animal{ @Override public void eat() { System.out.println("狗吃东西"); } public static void yaoRen(){ System.out.println("狗咬人"); } } class Monkey extends Animal{ @Override public void eat() { System.out.println("猴子吃香蕉"); } } public class TestAnimal {//测试类 public static void main(String[] args) { Cat cat = new Cat(); Dog dog = new Dog(); //多态环境下对成员方法的调用 Animal monkey = new Monkey();//默认自动转换,向上转型 //编译看左边,运行看右边。 //向上转型的作用是:提高程序的扩展性。 feedAnimal(cat); feedAnimal(dog); feedAnimal(monkey); /* 多态优点:父类引用可以表示子类对象,提升程序扩展性 缺点:父类不能调用子类中特有的方法,也不能调用成员变量和静态方法 */ //多态环境下对成员变量的调用 System.out.println(monkey.num);//调用的是动物类中的成员变量。 //编译和运行都看等号左边。 //变量不存在被子类覆写这一说法,只有方法存在覆写。 } static void feedAnimal(Animal animal){//方法参数也具有多态性 if(animal instanceof Dog){ /* instanceof关键字用法:(父类型引用 instanceof 子类) 判断父类引用实际表示的对象是否为指定类型*/ Dog dog = (Dog)animal; /*强制转型,向下转型,将Aniaml父类型转为Dog子类型,不能直接进行强制转换,要先判断animal中实际传入的类型是什么类型*/ //向下转型的作用是:为了使用子类中的特有方法。 dog.yaoRen();//调用子类中特有的方法 //编译和运行都看左边。 dog.eat(); } else animal.eat(); } } /* 多态优点:父类引用可以表示子类对象,提升程序扩展性 缺点:父类不能调用子类中特有的方法,也不能调用子类成员变量和静态方法 */
final关键字
用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变
- 修饰类、属性和方法
public class Car {
static final String name = "bm";
/*要么在定义之初就直接赋值,因为在定义之初就赋了值,
那么在所有对象中就不能改变,所以建议用static修饰,
在内存中只有一份,节省空间。
*/
final int price;
public Car(int price){
//要么在构造方法中赋值,每个对象的price都不同,但也只能赋一次值
this.price=price;
}
}
public class TestCar {//测试类
public static void main(String[] args) {
Car car = new Car(500000);
System.out.println(car.name+car.price);
Car car2 = new Car(600000);
System.out.println(car2.name+car2.price);
}
}
接口
-
面向接口编程
- 关心实现类有何能力,而不关心实现细节
- 面向接口的约定而不考虑接口的具体实现
-
接口存在的意义:
java中一个类只能有一个父类,所以用接口可以实现多继
承的逻辑 。
-
从本质上讲,接口是一种特殊的抽象类,这种抽象类中包含抽象方法。
-
接口的定义:使用 interface 关键字用来声明一个接口。
-
[访问修饰符] interface 接口名称 [extends 其他的接口名1,….其他的接口名n] { // 声明常量 抽象方法 静态方法 默认方法 }
-
**接口的使用:**类使用implements关键字实现接口。在类声明中,Implements关
键字放在class声明后面。
-
[访问修饰符] class 类名 implements 接口名1,接口名2……{ }
-
类可以实现多个接口
[访问修饰符] class 类名 extends 父类名 implements 接口名1,接口名2……{ }
-
接口的特性
-
接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字
-
接口中方法可以是抽象的,静态的,默认的
-
接口中声明的属性默认为 public static final 的
-
与继承关系类似,接口与实现类之间存在多态性
-
一个接口能继承其它多个接口
-
当类实现接口的时候,类要实现接口中所有的抽象方法。否则,类必须
声明为抽象的类
-
public class Car {
private String name;
private float price;
public Car(String name, float price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {//重写Object类中的toString方法,若不重写就会将对象的地址按16进制字符串输出
return "Car{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
@Override
public boolean equals(Object obj) {//重写equals方法
Car car = (Car)obj;//向下转型,将Object类型转为它的子类Car类型
return this.name== car.name&&this.price==car.price;
}
}
public interface CanCry {//接口用interface修饰
int i = 10;//静态常量默认static final修饰
public static void jiao(){//静态方法
System.out.println("会叫");
}
public void cry();//默认方法,通过子类对象调用
/*
接口中无构造方法。接口也不能创建对象
*/
}
class Cat implements CanCry{
@Override
public void cry() {
System.out.println("我是猫,我的叫声是喵喵喵");
}
}
class Dog implements CanCry{
@Override
public void cry() {
System.out.println("我是狗,我的叫声是汪汪汪");
}
}