Java零基础学习Day13——面向对象进阶

一、static

1. 静态变量

特点

被该类所有对象公用

不属于对象,属于类

随着类的加载而加载,优先于对象出现

调用方式

类名调用(推荐)、对象名调用

例子

package staticdemo1;
public class StudentTest {
    public static void main(String[] args) {
        Student.teacherName = "王老师";
        Student s1 = new Student();
        s1.setName("张三");
        s1.setAge(20);
        s1.setGender("男");
//      s1.teacherName = "王老师";
        s1.show();
        s1.study();

        Student s2 = new Student("李四", 21, "女");
        s2.show();
        s2.study();
        
        Student s3 = new Student("王五", 22, "男");
        s3.show();
        s3.study();
    }
}
package staticdemo1;
public class Student {
    private String name;
    private int age;
    private String gender;
//  public String teacherName;
    public static String teacherName;

    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public void study() {
        System.out.println(name + " 正在学习.");
    }
    public void show(){
        System.out.println(name + ","+age+","+gender+","+teacherName);
    }
}

2. 静态方法

特点

多用在测试类和工具类中, JavaBean类中很少会用

调用方式

类名调用(推荐)、对象名调用

3. 工具类

简单介绍

JavaBean类

用于描述一类事物的类

比如Student、Cat等

测试类

用来检查其他类是否书写正确

带有main方法的类,是程序的入口

工具类用来帮我们做一些事情的类

私有化构造方法,目的是为了不让外界创建其对象

方法定义为静态

例子1

数组的打印和求平均

package staticdemo2;

public class ArrayUtil {
    //私有化构造方法
    private ArrayUtil() {

    }
    public static String printArray(int[] arr) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1) {
                sb.append(arr[i]);
            }else{
                sb.append(arr[i] + ",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    public static double getAverage(double[] arr) {
        double sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        return sum / arr.length;
    }
}
package staticdemo2;

public class TestDemo { // 测试类
    public static void main(String[] args) {
        //测试工具类中的两个方法是否正确
        int[] arr = {1, 2, 3, 4, 5};
        String str = ArrayUtil.printArray(arr);
        System.out.println(str);
        double[] arr1 = {1.1, 2.2, 3.3, 4.4, 5.5};
        double avg = ArrayUtil.getAverage(arr1);
        System.out.println(avg);
    }
}

例子2

学生工具列,获取集合中最大年龄

package staticdemo1;
public class Student {
    private String name;
    private int age;
    private String gender;


    public Student() {
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
package staticdemo1;
import java.util.ArrayList;
public class StudentTool {
    private StudentTool() {}
    public static int getMaxAgeStudent(ArrayList<Student> list) {
        int maxAge = list.get(0).getAge();
        for (int i = 1; i < list.size(); i++) {
            int tempAge = list.get(i).getAge();
            if (tempAge > maxAge) {
                maxAge = tempAge;
            }
            }
        return maxAge;
    }
}
package staticdemo1;
import java.util.ArrayList;
public class StudentTest {
    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<Student>();
        Student s1 = new Student("zhangsan", 18, "male");
        Student s2 = new Student("lisi", 19, "female");
        Student s3 = new Student("wangwu", 20, "male");
        list.add(s1);
        list.add(s2);
        list.add(s3);

        //调用工具类中的方法
        int maxAge = StudentTool.getMaxAgeStudent(list);
        System.out.println("最大年龄为:" + maxAge);
    }
}

 

4. static的注意事项

内容

静态方法只能访问静态

非静态方法可访问所有

静态方法中没有this关键字(隐含)

代码解释、内存解释

听麻了,脑子不转了,就记住有上面三个注意事项吧

5. 重新认识main方法

public被JVM调用,访问权限足够大
static

被JVM调用,不用创建对象,直接类名访问

main是静态,所以测试类里的方法都得是静态

void被JVM调用,不需要给JVM返回值
main一个通用名称,不是关键字,可被JVM识别
String[] args现在没用,以前用于接收键盘录入数据,现在用scanner

二、继承

1. 基础内容

面向对象三大特征:封装、继承、多态

继承:关键字extends可以让两个类建立继承关系,即基类、派生类

格式:public class 基类 extends 派生类{ }

特点:Java只支持单继承、不支持多继承、但支持多层继承

           每一个类都直接或间接地继承于Object

          派生类只能访问基类中非私有的成员

使用继承的好处:提高代码的复用性、在基类的基础上增强更多功能

 

2. 练习

可用画图法理清继承关系,画图从下往上画,写代码时从上往下写(上是基类,下是派生类)

package oopextendsdemo1;
public class Animal {
    //权限修饰符,不是public而是private的话只能在本类中访问
    public void eat() {
        System.out.println("吃东西");
    }
    public void drink() {
        System.out.println("喝水");
    }
}
package oopextendsdemo1;
public class Cat extends Animal {
    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}
package oopextendsdemo1;
public class Dog extends Animal {
    public void lookHome() {
        System.out.println("狗看家");
    }
}
package oopextendsdemo1;
public class Ragdoll extends Cat {
}
package oopextendsdemo1;
public class LiHua extends Cat{
}
package oopextendsdemo1;
public class Husky extends Dog{
    public void breakHome() {
        System.out.println("哈士奇拆家");
    }
}
package oopextendsdemo1;
public class Teddy extends Dog {
    public void touch(){
        System.out.println("泰迪又在蹭我的腿了~");
    }
}
package oopextendsdemo1;
public class Test {
    public static void main(String[] args) {
        //1. 创建布偶猫对象
        Ragdoll rd = new Ragdoll();
        rd.eat();
        rd.drink();
        rd.catchMouse();

        System.out.println("======================");

        //2. 创建哈士奇对象
        Husky hs = new Husky();
        hs.eat();
        hs.drink();
        hs.lookHome();
        hs.breakHome();
    }
}

 

3. 派生类能继承基类中的哪些内容

表格总结

public(其他的非私有同理)private
构造方法NONO
成员变量YES

YES

成员方法虚方法YES非虚方法NO

构造方法:违背了构造方法的名字和类名(class)不一致

成员变量:private是继承了但不能直接使用

成员方法:只有基类的虚方法才能被派生类继承

虚方法表:将经常使用的方法单独放置,非private、非static、非final。每一个基类都会将自己的虚方法表传给派生类,派生类会在此基础上进行添加。

误区

基类私有的东西,派生类就无法继承

基类非私有的东西,就被派生类继承下来

4. 继承中的访问特点

成员变量的访问特点

就近原则:谁离得近,就用谁。先在局部位置找,本类成员位置找,父类成员位置找,逐级进行

重名的成员变量:

System.out.println(name);// 从局部开始往上找
System.out.println(this.name);// 从本类成员位置开始往上找
System.out.println(super.name);// 从基类成员位置开始往上找
package oopextendsdemo1;
public class Test {
    public static void main(String[] args) {
       Nv n = new Nv();
       n.nvShow();
    }
}
class Mu{
    String name = "Mu";
}
class Nv extends Mu{
    String name = "Nv";
    public void nvShow(){
        String name = "nvshow";
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
}

 

成员方法的访问特点

就近原则、super调用访问基类

和成员变量是一样的的逻辑,不同点在于成员方法只有两个即this(本类)和super(基类)

package oopextendsdemo1;
public class Test {
    public static void main(String[] args) {
       Student s = new Student();
       s.lunch();
       System.out.println("=======================");
       OverseaStudents os = new OverseaStudents();
       os.lunch();
    }
}

class Person{
    public void eat(){
        System.out.println("吃米饭、吃菜");
    }
    public void drink(){
        System.out.println("喝开水");
    }
}

class OverseaStudents extends Person{
    public void lunch(){
        this.eat();
        this.drink();
        super.eat();
        super.drink();
    }
    @Override
    public void eat(){
        System.out.println("吃意大利面、吃意大利菜");
    }
    @Override
    public void drink(){
        System.out.println("喝凉水");
    }
}
class Student extends Person{
    public void lunch(){
        this.eat();
        this.drink();
        super.eat();
        super.drink();
    }
}

 

方法重写

方法的重写:当基类不满足派生类的需求时,使用一模一样的方法声明

                     @Override是放在重写方法上,校验语法是否正确

                      本质是覆盖了虚方法表中的方法

方法重写的注意事项:重写的方法尽量和基类一致,名称、形参列表必须一致

                                   只有被添加到虚方法表中的方法才能被重写

                                   方法重写时,访问权限派生类>基类,返回值类型派生类<基类

方法重写练习

package oopextendsdemo1;
public class Dog {
    public void eat() {
        System.out.println("狗在吃狗粮");
    }
    public void drink() {
        System.out.println("狗在喝水");
    }
    public void lookHome() {
        System.out.println("狗在看家");
    }
}
package oopextendsdemo1;
public class Husky extends Dog{
    public void breakHome() {
        System.out.println("哈士奇拆家");
    }
}
package oopextendsdemo1;
public class ShaPi extends Dog{
    @Override
    public void eat() {
        super.eat();    //System.out.println("沙皮在吃狗粮");
        System.out.println("狗啃骨头");
    }
}
package oopextendsdemo1;
public class ChineseDog extends Dog {
    @Override
    public void eat() {
        System.out.println("中犬在吃剩饭");
    }
}
package oopextendsdemo1;
public class Test {
    public static void main(String[] args) {
        Husky h = new Husky();
        h.eat();
        h.drink();
        h.lookHome();
        h.breakHome();
        System.out.println("--------------------");

        ShaPi s = new ShaPi();
        s.eat();
        s.drink();
        s.lookHome();
        System.out.println("--------------------");

        ChineseDog c = new ChineseDog();
        c.eat();
        c.drink();
        c.lookHome();
    }
}

 

构造方法的特点

基类的构造方法是不能被派生类继承

无参

派生类中所有构造方法默认先访问基类的无参构造,再执行自己的

派生类构造方法的第一行有默认的super()

(派生类初始化前,一定要调用基类构造方法先完成其数据空间的初始化)

package oopextendsdemo2;

public class Person {
    String name;
    int age;
    public Person() {
        System.out.println("基类的无参构造");
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
package oopextendsdemo2;

public class Student extends Person {
    public Student() {
        //派生类构造方法中隐藏的super()去访问基类的无参构造
        super();
        System.out.println("派生类的无参构造");
    }
}
package oopextendsdemo2;

public class Test {
    public static void main(String[] args) {
        Student s = new Student();
    }
}

 

有参

手动写super进行基类有参构造调用

person同上

package oopextendsdemo2;

public class Student extends Person {
    public Student() {
        //派生类构造方法中隐藏的super()去访问基类的无参构造
        super();
        System.out.println("派生类的无参构造");
    }
    public Student(String name, int age) {
        super(name, age);
    }
}
package oopextendsdemo2;

public class Test {
    public static void main(String[] args) {
        Student s = new Student("zhagnsan", 20);
        System.out.println(s.name+","+s.age);
    }

 

5. this、super使用总结

this:表示当前方法调用者的地址值

super:代表基类存储空间

访问成员变量访问成员方法访问构造方法
this

this.成员变量

访问本类成员变量

this.成员方法(...)

访问本类成员方法

this(...)

访问本类构造方法

super

super.成员变量

访问基类成员变量

super.成员方法(...)

访问基类成员方法

super(...)

访问基类构造方法

this(...)一般在需要给默认值的场景下使用

package oopextendsdemo2;

public class Student {
   String name;
   int age;
   String school;

   public Student() {
       //表示调用本类其他构造方法
       //细节:虚拟机就不会再添加super()了
       this(null,0,"传智教育");
   }
   public Student(String name, int age, String school) {
       this.name = name;
       this.age = age;
       this.school = school;
   }
}
package oopextendsdemo2;

public class Test {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println(s.name+","+s.age);
    }
}

 6. 练习-带有继承结构的标准JavaBean类

package oopextendsdemo3;

public class Employee {
    private String id;
    private String name;
    private double salary;

    public Employee() {}

    public Employee(String id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public void work() {
        System.out.println("员工在工作");
    }
    public void eat() {
        System.out.println("吃米饭");
    }
}
package oopextendsdemo3;

public class Manager extends Employee{
    private double bounus;

    public Manager() {
    }

    public Manager(String id, String name, double salary, double bounus) {
        super(id, name, salary);
        this.bounus = bounus;
    }

    public double getBounus() {
        return bounus;
    }

    public void setBounus(double bounus) {
        this.bounus = bounus;
    }

    @Override
    public void work() {
        System.out.println("经理在管理其他人");
    }
}
package oopextendsdemo3;

public class Cook extends Employee{
    public Cook() {
    }

    public Cook(String id, String name, double salary) {
        super(id, name, salary);
    }

    @Override
    public void work() {
        System.out.println("厨师在烹饪");
    }
}
package oopextendsdemo3;

public class Test {
    public static void main(String[] args) {
        Manager m = new Manager("001", "小韩", 10000, 2000);
        System.out.println(m.getId()+","+m.getName()+","+m.getSalary()+","+m.getBounus());
        m.work();
        m.eat();
        System.out.println("=====================");
        Cook c = new Cook("002", "小曹", 8000);
        System.out.println(c.getId()+","+c.getName()+","+c.getSalary());
        c.work();
        c.eat();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值