面向对象中级编程
方法重写
- 方法重写:子类重写父类的方法,子类方法与父类方法名相同,参数列表相同,返回值类型相同
- 父类方法被重写后,子类对象调用该方法,会调用子类方法
public class Demo extends Demo {public static void main(String[] args) {Demo demo = new Demo();demo.print();//输出子类方法demo.show();//输出父类方法}public void print() {System.out.println("子类方法");}
}class Demo {public void print() {System.out.println("父类方法");}public void show() {System.out.println("父类方法");}
}
方法重载
- 方法重载:多个方法名相同,参数列表不同,返回值类型相同
public class Demo {public static void main(String[] args) {Demo demo = new Demo();demo.print();demo.print(10);}
}class Demo {public void print() {System.out.println("父类无参方法");}public void print(int a) {System.out.println("父类有参方法");}
}
方法的重载和重写的对比
- 方法重写:
- 子类重写父类方法,子类方法与父类方法名相同,参数列表相同,返回值类型相同
- 父类方法被重写后,子类对象调用该方法,会调用子类方法
- 如果想要访问父类方法,可以使用super.方法名
- 方法重载:多个方法名相同,参数列表不同,返回值类型相同
- 根据传入的参数,编译器会自动选择最匹配的函数
this 关键字
- this关键字代表当前对象,this关键字不能用在静态方法中。
- 哪一个对象调用this,this就代表哪一个对象。
- 可以在类的成员方法中,调用本类的属性,方法,
- 在一个构造器当中可以调用其他的构造函数,但是this的语句必须置于第一条语句this(),或者this(参数列表)
- 大部分情况下可以省略,但是在区分局部变量和实例变量时,this关键字必须使用。
举例
public void setName(String name) {this.name = name;//this代表当前类的实例对象
}
- 用法:构造方法,this.属性名,this.方法名,this.构造方法名
举例
Demo() {public class Student {private int age;private String name;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}//有参数的构造器public Student(int age, String name) {//在一个构造器当中可以调用其他的构造函数,但是this的语句必须置于第一条语句this(12);//this.age = age;this.name = name;}public Student(int age) {System.out.println("给age进行了赋值");this.age = age;}public Student(String name) {this.name = name;}//无参数构造器public Student() {//this();System.out.println("我是一个无参构造函数");}//输出当前对象的信息public String printInfo() {return "Student{" +"age=" + age +", name='" + name + '\'' +'}';}public static void main(String[] args) {Student student = new Student(20, "张三");System.out.println(student.printInfo());}}}
super 关键字
- super关键字代表父类的对象,super关键字不能用在静态方法中。
- super被用在子类中,super代表的是父类的对象。
- super的语法是“super.属性名”、“super.方法名”
- 在一个构造器当中可以调用其他的构造函数,但是super的语句必须置于第一条语句super(),或者super(参数列表),即不能与this在构造器中同时出现
- super大部分情况下是可以省略的
举例:
class Creature {public Creature() {System.out.println("Creature无参数的构造器");}
}class Animal extends Creature {public Animal(String name) {System.out.println("Animal带一个参数的构造器,该动物的name为" + name);}public Animal(String name, int age) {this(name);System.out.println("Animal带两个参数的构造器,其age为" + age);}
}public class Dog extends Animal {public Dog() {super("汪汪队阿奇", 3);//父类有带两个参数的构造器,那么子类中必须调用父类的带两个参数的构造器,输出 :Animal带两个参数的构造器,该动物的name为汪汪队阿奇System.out.println("Dog无参数的构造器");}public static void main(String[] args) {new Dog();}
}
this 和 super 的区别
- this:先从子类中进行寻找,如果找不到,那么就找对应的父类,如果父类中还没有,那么我们就找父类中的父类,直到找到为止,如果找不到,就会抛出异常
- super:先从父类中进行寻找,如果找不到,那么就找对应的父类,如果父类中还没有,那么我们就找父类中的父类,直到找到为止,如果找不到,就会抛出异常
public class MyTest {public static void main(String[] args) {new Cat();}
}//父类,Animal类
class Animal {//构造函数public Animal() {super();System.out.println("1:Animal类的无参数构造函数执行");}public Animal(int i) {super();System.out.println("2:Animal类的有int参数构造函数执行");}
}//子类,Cat类
class Cat extends Animal {//构造函数public Cat() {this("");System.out.println("3:Cat类的无参数构造函数执行");}public Cat(String str) {super(5);System.out.println("4:Cat类的有String参数构造函数执行");}
}
- 执行顺序
main方法中创建Cat对象:new Cat();
→ 调用Cat类的无参构造函数。
Cat()无参构造函数的第一行是this(“”);
→ 调用本类的带String参数的构造函数Cat(String str)。
Cat(String str)构造函数的第一行是super(5);
→ 调用父类Animal的带int参数的构造函数Animal(int i)。
Animal(int i)构造函数执行:
先调用super();(隐式调用Object类的构造函数)
打印:2:Animal类的有int参数构造函数执行
→ 父类构造函数执行完毕,回到Cat(String str)。
继续执行Cat(String str)构造函数的剩余部分:
打印:4:Cat类的有String参数构造函数执行
→ 带参构造函数执行完毕,回到Cat()无参构造函数。
继续执行Cat()无参构造函数的剩余部分:
打印:3:Cat类的无参数构造函数执行
→ 整个对象创建过程完成。
面向对象三大特征
- 封装,继承,多态
封装
封装:将属性私有化,属性的访问权限设置为private,然后提供getter和setter方法,通过getter和setter方法来访问属性
举例:
public class Person {private int age;private String name;public void setAge(int age) {this.age = age;}public int getAge() {return age;}public void setName(String name) {this.name = name;}public String getName() {return name;}
}
继承
- 继承的语法:
- 减少代码的冗余,习惯性的把重复的代码声明为一个父类,然后使用其他的类来继承父类,使用extends
- 子类继承了父类之后,那么父类中的所有的属性跟方法,构造函数都无条件的被子类所使用
public class Person {public int age;public String name;public void eat() {System.out.println("人类可以吃东西");}
}class Student extends Person {public String school;public void run() {System.out.println("学生喜欢跑步");}
}class Son extends Student {public String car;public void sing() {}
}class StudentTest {public static void main(String[] args) {
//对于继承来说,当一个类继承了另外一个类,那么就无条件的继承父类中的所有属性和所有的方法Student student = new Student();student.age = 18;student.name = "张三";student.school = "宝文理";
//调用的时候先看当前自己的类中有没有?没有的话就找父类,如果父类还没有,那就找父类的父类student.eat();Son son = new Son();son.eat();}
}
多态
- 多态:一个对象可以有不同的形态,多态表现形式:父类引用指向子类对象,(接口和继承)
public class Animal {public void eat() {System.out.println("吃吃吃");}public void sleep() {System.out.println("睡觉睡觉睡觉");}
}public class Dog extends Animal {@Overridepublic void eat() {System.out.println("吃吃吃吃吃");}
}public class Test {public static void main(String[] args) {Animal animal = new Dog();animal.eat();//调用的是子类的方法animal.sleep();//父类中的方法没有被重写,所以调用的是父类的方法}
}
四种访问权限修饰符:
public: 全部都可以访问
protected: 其他包的非子类访问不到,其他都可以访问得到
默认:其他包的非子类和其他包的子类访问不到
private: 只有在自己的类中才能访问得到
public class Demo01 {public int num1 = 10;protected int num2 = 20;int num3 = 30;private int num4 = 40;public void a() {System.out.println("a");}protected void b() {System.out.println("a");}void c() {System.out.println("a");}private void d() {System.out.println("a");}public static void main(String[] args) {Demo01 demo01 = new Demo01();System.out.println(demo01.num1);System.out.println(demo01.num2);System.out.println(demo01.num3);System.out.println(demo01.num4);demo01.a();demo01.b();demo01.c();demo01.d();}
}//研究不同的类之中
class AA {public static void main(String[] args) {Demo01 demo01 = new Demo01();System.out.println(demo01.num1);System.out.println(demo01.num2);System.out.println(demo01.num3);//System.out.println(demo01.num4);demo01.a();demo01.b();demo01.c();//demo01.d();}
}