继承
继承的概述
继承是面向对象三大特征之一,可以使子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。
父类
package 继承;
public class Fu {
public void show(){
System.out.println("show方法被调用");
}
}
子类
package 继承;
public class Zi extends Fu{
public void method(){
System.out.println("method方法被调用");
}
}
Demo
package 继承;
public class Demo {
public static void main(String[] args) {
//创建对象,调用方法
Fu f = new Fu();
f.show();
Zi z = new Zi();
z.method();
z.show();
}
}
继承的好处和弊端
继承中变量的访问特点
也就是,访问一个变量是,若子类的方法中有,输出子类方法中的变量值,若没有,看子类的类中(成员变量)是否存在,若没有,然后看父类中是否存在。
super关键字
//父类
package 继承;
public class Fu {
public int age = 50;
}
//子类
package 继承;
public class Zi extends Fu{
public int age = 28;
public void show()
{
int age = 30;
System.out.println(age);
//访问本类的成员变量age
System.out.println(this.age);
//访问父类的成员变量age
System.out.println(super.age);
}
}
//调试
package 继承;
public class Zi extends Fu{
public int age = 28;
public void show()
{
int age = 30;
System.out.println(age);
//访问本类的成员变量age
System.out.println(this.age);
//访问父类的成员变量age
System.out.println(super.age);
}
}
输出
继承中构造方法的访问特点
//父类
public class Fu {
public Fu (){}
public Fu(int age){
System.out.println("Fu中带参构造方法被调用");
}
}
//子类
public class Zi extends Fu{
public Zi(){
super(20);//访问父类的构造方法
System.out.println("Zi中无参构造方法被调用");
}
public Zi(int age){
super(20);
System.out.println("Zi中带参构造方法被调用");
}
}
//测试类
public class Demo {
public static void main(String[] args) {
Zi z = new Zi();
Zi z2 = new Zi(20);
}
}
继承中成员方法的访问特点
//父类
public class Fu {
public void show(){
System.out.println("Fu中show()方法被调用");
}
}
//子类
public class Zi extends Fu{
public void method(){
System.out.println("Zi中method()方法被调用");
}
public void show(){
super.show();
System.out.println("Zi中show()方法被调用");
}
}
//测试类
public class Demo {
public static void main(String[] args) {
//创建对象,调用方法
Zi z = new Zi();
z.method();
z.show();
}
}
super内存图
方法或构造方法的执行顺序遵循“进栈出栈”原理,堆内存中存储的是变量的地址。
方法重写
//手机类
public class phone {
public void call(String name){
System.out.println("给" + name + "打电话");
}
}
//新手机类
public class newphone extends phone{
@Override
public void call(String name){
System.out.println("开启视频功能");
//System.out.println("给" + name + "打电话");
super.call(name);
}
}
//测试类
public class phonedemo {
public static void main(String[] args) {
//创建对象,调用方法
phone p = new phone();
p.call("林青霞");
System.out.println("--------");
newphone np = new newphone();
np.call("胡歌");
}
}
方法重写注意事项
//父类
public class Fu {
private void show(){
System.out.println("Fu中show()方法被调用");
}
public void method(){
System.out.println("Fu中method()方法被调用");
}
}
//子类
//在子类中重写父类的方法
public class Zi extends Fu{
/*
@Override报错,证明父类中的private方法子类是不能调用的
private void show(){
System.out.println("Zi中show()方法被调用");
}
*/
/*
@Override没有报错
public void method(){
System.out.println("Zi中method()方法被调用");
}
*/
@Override
void method(){
//默认的方法访问权限比public低,所以不能访问父类,如果将父类方法也改为默认的,就可以继承父类,并且子类此时可以为public或默认的
System.out.println("Zi中method()方法被调用");
}
}
Java中继承的注意事项
比如:儿子只能继承父亲,不能同时继承父亲和母亲,即不支持多继承,支持单继承
支持多层继承:
案例:老师和学生
①定义老师类
package TeaStu;
public class Teacher {
private String name;
private int age;
public Teacher() {
}
public Teacher(String name, int age) {
this.name = name;
this.age = age;
}
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 void teach(){
System.out.println("用爱成就每一位学生");
}
}
②定义学生类
package TeaStu;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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 void study(){
System.out.println("好好学习,天天向上");
}
}
③定义测试类
package TeaStu;
public class Demo {
public static void main(String[] args) {
//创建老师类对象进行测试
Teacher t1 = new Teacher();
t1.setName("林青霞");
t1.setAge(30);
System.out.println(t1.getName() + "," + t1.getAge());
t1.teach();
Teacher t2 = new Teacher("风清扬", 30);
System.out.println(t2.getName() + "," + t2.getAge());
t2.teach();
}
}
④共性抽取父类,定义人类
package Test;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
⑤定义老师类,继承人类,并给出自己的特有方法
package Test;
import Test.Person;
public class Teachers extends Person {
public Teachers() {
}
public Teachers(String name, int age) {
//因为老师类中没定义private变量,继承父类的person带参构造方法即可
super(name, age);
}
public void tecch(){
System.out.println("用爱成就每一位学生");
}
}
⑦定义测试类
package Test;
import TeaStu.Teacher;
public class PersonDemo {
public static void main(String[] args) {
//创建老师类并进行测试
Teachers t1 = new Teachers();//系统给的默认的无参构造方法
t1.setName("林青霞");
t1.setAge(30);
System.out.println(t1.getName() + "," + t1.getAge());
t1.tecch();
Teacher t2 = new Teacher("风清扬", 33);
System.out.println(t2.getName() + "," + t2.getAge());
t2.teach();
}
}
案例:猫和狗
①定义动物类
package catdog;
public class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
②定义猫类,狗类不再给出,方法类似。
package catdog;
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
③定义测试类
package catdog;
public class AnimalDemo {
public static void main(String[] args) {
Cat c1 = new Cat();
c1.setName("加菲猫");
c1.setAge(5);
System.out.println(c1.getName() + "," + c1.getAge());
c1.catchMouse();
Cat c2 = new Cat("加菲猫",5);
System.out.println(c2.getName() + "," + c2.getAge());
c2.catchMouse();
}
}
修饰符
包
包的概述和使用
一般我们直接使用idea建包,非常方便。
导包
导包的概述和使用
修饰符分为
权限修饰符
状态修饰符
final(最终态)
有点像const,总之被final修过的方法、变量、不能被重写、重新赋值、继承。
final修饰局部变量
//学生类
package Final;
public class Student {
public int age = 20;
}
//测试类
package Final;
/*
测试类
*/
public class FinalDemo {
public static void main(String[] args) {
//final修饰基本变量类型
final int age = 20;
//age = 100;会报错,因为final修饰的变量已为常量
System.out.println(age);
//final修饰引用类型变量
final Student s = new Student();
s.age = 100;
System.out.println(s.age);
// s = new Student();
// 会报错,因为final修饰引用类型变量时,引用类型的地址不能改变,但地址里面的内容可以改变
}
}
static(静态)
//学生类
package Static;
public class Student {
public String name;
public int age;
// public String university;//学校
public static String university;//学校
public void show(){
System.out.println(name + "," + age + "," + university);
}
}
//测试类
package Static;
public class StaticDemo {
public static void main(String[] args) {
//被所有对象共享的成员用静态修饰
Student.university = "上海戏剧学院";//通过类名来访问
Student s1 = new Student();
s1.name = "林青霞";
s1.age = 30;
// s1.university = "上海戏剧学院";这是通过对象名调用
s1.show();
Student s2 = new Student();
s2.name = "风清扬";
s2.age = 20;
// s2.university = "上海戏剧学院";
s2.show();
}
}
static访问特点
- 非静态成员方法可以访问所有静态、非静态成员变量和方法
- 静态的成员方法只能访问静态的成员变量和成员方法。
package Static;
public class Student {
//非静态成员变量
private String name = "林青霞";
//静态成员变量
private static String university = "传智大学";
//非静态成员方法
public void show1(){
}
public void show2(){
System.out.println(name);
System.out.println(university);
show1();
show3();
}
//静态成员方法
public static void show3(){
}
public static void show4(){
// System.out.println(name);
System.out.println(university);
// show1();
show3();
}
}
多态
多态概述
//父类
package manyForm;
public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}
//有继承,有方法重写
package manyForm;
public class Cat extends Animal {
//有父类引用指向子类对象
@Override
public void eat() {
super.eat();
}
}
//有父类引用指向子类对象
package manyForm;
public class Cat extends Animal {
//有父类引用指向子类对象
@Override
public void eat() {
super.eat();
}
}
多态中成员访问特点
//父类
package manyForm;
public class Animal {
public int age = 40;
public void eat(){
System.out.println("动物吃东西");
}
}
//子类
package manyForm;
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
//有父类引用指向子类对象
@Override
public void eat(){
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫捉迷藏");
}
}
//测试类
package manyForm;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
//多态形式访问成员变量,编译运行都看左边
System.out.println(a.age);
//System.out.println(a.weight);报错
//多态形式访问成员方法,编译看左边,运行看右边
a.eat();
//a.playGame();报错
}
}
因为成员方法有重写而成员变量没有
多态的好处和弊端
package manyForm;
/*
动物操作类
*/
public class AnimalOperator {
/*
public void useAnimal (Cat c){//Cat c = new Cat();
c.eat();
}
public void useAnimal (Dog d){//Dog d = new Dog();
d.eat();
}
*/
public void useAnimal(Animal a){
//Animal a = new Cat();
//Animal a = new Dog();
//...
a.eat();
}
}
//测试类
package manyForm;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//创建动物操作类对象,调用方法
AnimalOperator ao = new AnimalOperator();
Cat c = new Cat();
ao.useAnimal(c);
Dog d = new Dog();
ao.useAnimal(d);
}
}
//父类
package manyForm;
public class Animal {
public int age = 40;
public void eat(){
System.out.println("动物吃东西");
}
}
//子类猫
package manyForm;
public class Cat extends Animal {
public int age = 20;
public int weight = 10;
//有父类引用指向子类对象
@Override
public void eat(){
System.out.println("猫吃鱼");
}
public void playGame(){
System.out.println("猫捉迷藏");
}
}
//子类狗
package manyForm;
public class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
//多态不能使用狗中特有的功能
public void lookDoor(){
System.out.println("狗看门");
}
}
多态中的转型
向下转型类似于数据类型的强制转换
package manyForm;
/*
测试类
向上转型:
从子到父
父类引用指向子类对象
向下转型:
从父到子
父类引用转为子类对象
*/
public class AnimalDemo {
public static void main(String[] args) {
//多态
Animal a = new Cat();//父类引用指向子类对象,向上转型
a.eat();
//a.playgame();执行也看左边
/*
//创建Cat类对象
Cat c = new Cat();
c.eat();
c.playGame();
*/
//向下转型
Cat c = (Cat)a;
c.eat();
c.playGame();
}
}
多态转型内存图解
猫和狗(多态版)
//动物类
package manyForm;
public class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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 void eat(){
System.out.println("动物吃东西");
}
}
//猫类
package manyForm;
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//测试类
package manyForm;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
a = new Cat("加菲", 5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
}
}
抽象类
package manyForm;
//抽象类
public abstract class Animal {
//抽象方法
public abstract void eat();
}
抽象类的特点
//动物类
package manyForm;
public abstract class Animal {
//抽象方法
public abstract void eat();
// 非抽象方法
public void sleep(){
System.out.println("睡觉");
}
}
//猫类package manyForm;
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//测试类
package manyForm;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//抽象类创建对象的方式,参照多态方式,通过子类对象来实例化
Animal a = new Cat();
a.eat();
a.sleep();
}
}
抽象类的成员特点
package manyForm;
public abstract class Animal {
private int age = 20;
private final String city = "北京";
public Animal() {}
public Animal(int age) {
this.age = age;
}
public void show() {
age = 40;
System. out . println(age); .
// city = "上海";
System.out.println(city);
}
public abstract void eat() ;
}
猫和狗(抽象类版)
//动物类
package manyForm;
public abstract class Animal {
private String name;
private int age;
public Animal(){
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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 abstract void eat();
}
//狗类
package manyForm;
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
}
//猫类
package manyForm;
public class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
//测试类
package manyForm;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,按照多态的方式
//无参构造方法
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
System.out.println("--------");
//带参构造方法
a = new Cat("加菲",5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
System.out.println("----------------------------");
Animal d = new Dog();
d.setName("哈士奇");
d.setAge(5);
System.out.println(d.getName() + "," + d.getAge());
d.eat();
System.out.println("--------");
//带参构造方法
d = new Dog("哈士奇",5);
System.out.println(d.getName() + "," + d.getAge());
d.eat();
}
}
接口
接口特点
//接口类
package InterFace;
public interface Jumpping {
public abstract void jump();
}
//猫类
package InterFace;
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
//测试类
package InterFace;
public class JumppingDemo {
public static void main(String[] args) {
//Jumpping j = new Jumpping();接口也不能被直接实例化
//接口的实例化采用多态的形式,用它的实现类对象来进行实例化
Jumpping j = new Cat();
j.jump();
}
}
接口的实现类:抽象类,可以不重写接口里的方法,但他的子类以后要继承他是还需要重写接口里的抽象方法
package InterFace;
public abstract class Dog implements Jumpping {
}
接口的成员特点
//接口类
package Interface;
public interface Inter {
public int num = 10;
public final int num2 = 20;
//public static final int num3 = 40;等价于int num3 = 40;
int num3 = 40;//默认,接口中的变量为常量并且被static修饰
//接口里面不能有构造方法
//public Inter(){};
//接口里面不能有非抽象方法
//public void show(){};
public abstract void method();
void show();//默认带了public abstract
}
//测试类
package Interface;
public class Interfacedemo {
public static void main(String[] args) {
Inter i = new InterImpl();
// i.num = 20;报错,为什么呢?因为接口中的成员变量默认为被final修饰
//所以接口中没有成员变量,是成员常量
System.out.println(i.num);
//i.num2 = 40;报错,被final修饰 不能重新赋值
System.out.println(i.num2);
System.out.println(Inter.num);
}
}
//类继承接口
package Interface;
//public class InterImpl implements Inter{
public class InterImpl extends Object implements Inter{//两种写法等价
public InterImpl (){
super();//一个类无父类,直接继承Object,有父类,间接继承Object
}
@Override
public void method() {
System.out.println("method");
}
@Override
public void show() {
System.out.println("show");
}
}
猫和狗(接口类)
//接口
package Demo;
public interface Jumpping {
public abstract void jump();
}
//抽象方法(动物类)
package Demo;
import javax.swing.*;
public abstract class Animal {
private String name;
private int age;
public Animal (){
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
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 abstract void eat();
}
//猫类
package Demo;
public class Cat extends Animal implements Jumpping {
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
//测试类
package Demo;
/*
测试类
*/
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,调用方法
Jumpping j = new Cat();
j.jump();
System.out.println("--------");
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
((Cat)a).jump();
//a.jump();
//代参构造方法
a = new Cat("加菲",5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
System.out.println("----------");
Cat c =new Cat();
c.setName( "加菲");
c.setAge(5);
System.out.println(c. getName( )+" , "+c. getAge());
c.eat();
c.jump();
}
}
类和接口的关系
/类和接口的关系
package Demo;
public class InterImpl extends Object implements Inter1,Inter2,Inter3 {//继承一个类的时候实现多个接口
}
//接口和接口的关系
package Demo;
public interface Inter2 extends Inter1,Inter3 {//接口和接口是继承关系,并且可以多继承
}
抽象类和接口的区别
案例:运动员和教练
代码思路:
代码直接看这里:代码讲解
形参和返回值
类名作为形参和返回值
类名作为形参要的是该类的对象
//猫类
package Demo;
public class Cat {
public void eat(){
System.out.println("猫吃鱼");
}
}
//猫操作
package Demo;
public class CatOperator {
public void useCat(Cat c){//Cat c = new Cat();
c.eat();
}
public Cat getCat(){
Cat c = new Cat();
return c;//c是Cat类型的一个对象
}
}
//测试类
package Demo;
public class CatDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
CatOperator co = new CatOperator();
Cat c = new Cat();
co.useCat(c);
Cat c2 = co.getCat();//new Cat()
c2.eat();
}
}
抽象类名作为形参和返回值
//Animal
package Demo;
public abstract class Animal {//Animal为抽象类,抽象类不能直接实例化,采用多态形式,通过子类传递过来
public abstract void eat();
}
//AnimalOperator
package Demo;
public class AnimalOperator {
public void useAnimal(Animal a){//Animal a = new Cat();
a.eat();
}
public Animal getAnimal(){
Animal a = new Cat();
return a;
}
}
//AnimalDemo
package Demo;
public class AnimalDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
AnimalOperator ao = new AnimalOperator();
Animal a = new Cat();
ao.useAnimal(a);
Animal a2 = ao.getAnimal();//new Cat();
a2.eat();
}
}
//Cat类
package Demo;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
接口名作为形参或返回值
//Jumpping
package itheima;
public interface Jumpping {//接口不能直接实例化,需要多态实现,创建对象,该接口的实现类对象
public abstract void jump();//void jump()
}
//操作类
package itheima;
public class JumppingOperator {
public void useJumpping(Jumpping j){
j.jump();
}
public Jumpping getJumpping(){
Jumpping j = new Cat();
return j;
}
}
//猫类
package itheima;
public class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
//测试类
package itheima;
public class Demo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.useJumpping(j);
System.out.println("--------");
Jumpping j2 = jo.getJumpping();//new Cat();
j2.jump();
}
}
声明:文章内容参考黑马程序员视频课