java5对象进阶

本学习笔记的图片和题目均来源于黑马程序员,本人小白一枚,如有错误请及时指出,感谢感谢

由于本文时间跨度有点长,代码过多,本文不一一列出代码

一.static

(1)static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量。

(2)被static修饰的成员变量,叫做静态变量
被static修饰的成员方法,叫做静态方法
(3)静态变量的特点:被该类所有对象共享

不属于对象,属于类。
随着类的加载而加载,优先于对象存在
调用方式:
类名调用(推荐)
对象名调用
(4)静态方法的特点:多用在测试类和工具类中
Javabean类中很少会用

调用方式:
类名调用(推荐)
对象名调用

(5)static内存图

 (6)工具类:帮助我们做一些事情的,但是不描述任何事物的类
Javabean类:用来描述一类事物的类。比如,Student,Teacher,Dog,Cat等
测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的入口。

(7)工具类特点:类名见名知意
私有化构造方法
方法定义为静态

 练习一

public class ArrayUtil {
    private ArrayUtil() {
    }

    public static String printArr(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 = (double)0.0F;

        for(int i = 0; i < arr.length; ++i) {
            sum += arr[i];
        }

        double avg = sum / (double)arr.length;
        return avg;
    }
}
public class TestDemo {
    public TestDemo() {
    }

    public static void main(String[] args) {
        int[] arr = new int[]{10, 20, 50, 34, 100};
        double[] arr1 = new double[]{(double)10.0F, (double)20.0F, (double)50.0F, (double)34.0F, (double)100.0F};
        String str = ArrayUtil.printArr(arr);
        double s = ArrayUtil.getAverage(arr1);
        System.out.println(str);
        System.out.println(s);
    }
}

 练习二

import java.util.ArrayList;

public class StudentUtil {
    private StudentUtil() {
    }

    public static int Max(ArrayList<Student> list) {
        int max = ((Student)list.get(0)).getAge();

        for(int i = 1; i < list.size(); ++i) {
            int tempAge = ((Student)list.get(i)).getAge();
            if (max < tempAge) {
                max = tempAge;
            }
        }

        return max;
    }
}
public class Student {
    private String name;
    private int age;
    private String gender;

    Student() {
    }

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

    public String getName() {
        return this.name;
    }

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

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return this.gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
import java.util.ArrayList;
import java.util.Scanner;

public class StudentTest {
    public StudentTest() {
    }

    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList();
        Scanner sc = new Scanner(System.in);

        for(int i = 0; i < 3; ++i) {
            String name = sc.next();
            int age = sc.nextInt();
            String gender = sc.next();
            Student stu = new Student(name, age, gender);
            list.add(stu);
        }

        int m = StudentUtil.Max(list);
        System.out.println(m);
    }
}

(8)static的注意事项

静态方法只能访问静态变量和静态方法。
非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法。
静态方法中是没有this关键字。

1.代码方面理解

2.内存方面理解

(9)重新认识main方法
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");}}
public:被JVM调用,访问权限足够大
static:被JVM调用,不用创建对象,直接类名访问,因为main方法是静态的,所以测试类中其他方法也需要是静态的。
void:被JVM调用,不需要给JVM返回值
main:一个通用的名称,虽然不是关键字,但是可以被JVM识别
String[] args:以前用于接收键盘录入数据的,现在没用。[]数组,String数据类型,args数组名。

空格分隔,代表有三个参数,传给args,如果没有空格,就是一个参数

 

二.继承

(1)面向对象三大特征:
1.封装:对象代表什么,就得封装对应的数据,并提供数据对应的行为。
2.继承:让类和类之间建立起父子关系

 

3.多态。

 (2)继承概述:Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系。
格式:public class Student extends Person {}
Student称为子类(派生类),Person称为父类(基类或超类)。
(3)使用继承的好处
可以把多个子类中重复的代码抽取到父类中,子类可以直接使用,减少代码冗余,提高代码的复用性。

(4)什么时候使用继承

当类与类之间,存在相同共性的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码

 

 (5)继承后子类的特点
子类可以得到父类的属性和行为,子类可以使用。
子类可以在父类的基础上新增其他功能,子类更强大。

(6)继承的特点

1. Java只能单继承:一个类只能继承一个直接父类。

单继承:一个子类只能继承一个父类
2:Java不支持多继承、但是支持多层继承。

不支持多继承:子类不能同时继承多个父类

多层继承:子类 A 继承父类日,父类B 可以继承父类 C

3.Java中所有的类都直接或者间接继承于Object类。

4.子类只能访问父类中非私有的成员

练习1:(自己设计一个继承体系)
现在有四种动物:布偶猫、中国狸花猫、哈士奇、泰迪。
暂时不考虑属性,只要考虑行为。
请按照继承的思想特点进行继承体系的设计。
四种动物分别有以下的行为:
布偶猫:吃饭、喝水、抓老鼠
中国狸花猫:吃饭、喝水、抓老鼠
哈士奇:吃饭、喝水、看家、拆家
泰迪:吃饭、喝水、看家、蹭一蹭

使用画图法分析继承体系

画图:从下往上画
下面:子类
上面:父类

写代码:从上往下写。
需要把子类中的共性内容抽取到父类中
核心:1.共性内容抽取
2.子类是父类中的一种

注意: 子类只能访问父类中非私有的成员

private:只能在本类中访问,子类无法访问。

public class Animal {
    public Animal() {
    }

    public void eat() {
        System.out.println("吃饭");
    }

    public void drink() {
        System.out.println("喝水");
    }
}
public class Cat extends Animal {
    public Cat() {
    }

    public void catchMouse() {
        System.out.println("捉老鼠");
    }
}

public class Dog extends Animal {
    public Dog() {
    }

    public void lookHome() {
        System.out.println("看家");
    }
}
public class Husky extends Dog {
    public Husky() {
    }

    public void breakHome() {
        System.out.println("拆家");
    }
}
public class LiHua extends Cat {
    public LiHua() {
    }
}
public class Ragdoll extends Cat {
    public Ragdoll() {
    }
}
public class Teddy extends Dog {
    public Teddy() {
    }

    public void Touch() {
        System.out.println("蹭一蹭");
    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Ragdoll ragdoll = new Ragdoll();
        LiHua lihua = new LiHua();
        Husky husky = new Husky();
        Teddy teddy = new Teddy();
        ragdoll.drink();
        ragdoll.eat();
        ragdoll.catchMouse();
        lihua.drink();
        lihua.eat();
        lihua.catchMouse();
        husky.eat();
        husky.drink();
        husky.lookHome();
        husky.breakHome();
        teddy.drink();
        teddy.eat();
        teddy.lookHome();
        teddy.Touch();
    }
}

(7)子类到底能继承父类中的哪些内容

 1.父类的构造方法不能被子类继承:如果能的话,父类的构造方法在子类中会和构造方法的特点冲突,所以不能被子类继承。

 如果一个类中没有构造方法,虚拟机会自动添加一个默认的

2.成员变量可以被继承

非私有,私有成员变量都可以被继承

非私成员变量可以直接被调用,私有成员变量要通过set和get方法被调用。

继承的内存图

非私有

 私有

 4.私有成员方法不能被继承,非私有成员方法可以被继承

虚方法表:父类生成虚方法表,表中可以存储非static,非private,非final修饰的成员方法,只有父类中的虚方法才能被子类继承,父类将虚方法表继承给子类,表中有非私有成员方法,没有私有成员方法,所以,非私有成员方法可以被继承,私有成员方法无法被继承。

 内存图 

 使用内存分析工具分析

(8)继承中:成员变量的访问特点

1.继承中成员变量直接访问特点:就近原则
就近原则:谁离我近,我就用谁。

先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。

 2.如果出现了重名的成员变量怎么办?

this调用:就近原则。
super调用:直接找父类。

 

 

class Fu {
    Fu() {
    }

    public void eat() {
        System.out.println("吃米饭");
    }

    public void drink() {
        System.out.println("喝开水");
    }
}
class Zi1 extends Fu {
    Zi1() {
    }

    public void Show() {
        this.eat();
        this.drink();
        super.eat();
        super.drink();
    }
}
class Zi2 extends Fu {
    Zi2() {
    }

    public void eat() {
        System.out.println("吃意大利面");
    }

    public void drink() {
        System.out.println("喝凉水");
    }

    public void Show() {
        this.eat();
        this.drink();
        super.eat();
        super.drink();
    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Zi1 z1 = new Zi1();
        Zi2 z2 = new Zi2();
        z1.Show();
        z2.Show();
    }
}

 (9)方法重写

1.方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法重写
2.书写格式
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
3.@Override重写注解
①.@Override是放在重写后的方法前,校验子类重写时语法是否正确。
②.加上注解后如果有红色波浪线,表示语法错误。


③.建议重写方法都加@Override注解,代码安全,优雅!

 4.方法重写的本质:覆盖虚方法表中的方法

 5.方法重写注意事项和要求
①.重写方法的名称、形参列表必须与父类中的一致。
②.子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解:空着不写<protected < public)
③.子类重写父类方法时,返回值类型子类必须小于等于父类
④.建议:重写的方法尽量和父类保持一致。
⑤.只有被添加到虚方法表中的方法才能被重写

练习一

 画图

public class Dog {
    public Dog() {
    }

    public void eat() {
        System.out.println("吃狗粮");
    }

    public void drink() {
        System.out.println("喝水");
    }

    public void lookHome() {
        System.out.println("看家");
    }
}
public class Husky extends Dog {
    public Husky() {
    }

    public void breakHome() {
        System.out.println("拆家");
    }

    public void Show() {
        this.eat();
        this.drink();
        this.lookHome();
        this.breakHome();
    }
}
public class sharPei extends Dog {
    public sharPei() {
    }

    public void eat() {
        super.eat();
        System.out.println("吃骨头");
    }

    public void Show() {
        this.eat();
        this.drink();
        this.lookHome();
    }
}
public class tianYuan extends Dog {
    public tianYuan() {
    }

    public void eat() {
        System.out.println("吃剩饭");
    }

    public void Show() {
        this.eat();
        this.drink();
        this.lookHome();
    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Husky h = new Husky();
        sharPei s = new sharPei();
        tianYuan t = new tianYuan();
        h.Show();
        s.Show();
        t.Show();
    }
}

 (10)继承中:构造方法的访问特点
父类中的构造方法不会被子类继承,但是可以通过super调用。
子类中所有的构造方法默认先访问父类中的无参构造,再执行自己的。
为什么?
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。
怎么调用父类构造方法的?
子类构造方法的第一行语句默认都是:super(),父类的空参构造,不写也默认存在,且必须在第一行。
如果想调用父类有参构造,必须手动写super进行调用。

 

 (11)this、super使用总结

this:理解为一个变量,表示当前方法调用者的地址值;
super:代表父类存储空间。

this

 

 练习一.带有继承结构的标准Javabean类
1.经理
成员变量:工号,姓名,工资,管理奖金
成员方法:工作(管理其他人),吃饭(吃米饭)
2.厨师
成员变量:工号,姓名,工资
成员方法:工作(炒菜),吃饭(吃米饭)

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 this.id;
    }

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

    public String getName() {
        return this.name;
    }

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

    public double getSalary() {
        return this.salary;
    }

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

    public void Work() {
        System.out.println("工作");
    }

    public void eat() {
        System.out.println("吃米饭");
    }
}
public class Manager extends Employee {
    private double bouns;

    public Manager() {
    }

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

    public double getBouns() {
        return this.bouns;
    }

    public void setBouns(double bouns) {
        this.bouns = bouns;
    }

    public void Work() {
        System.out.println("管理其他人");
    }
}
public class Cook extends Employee {
    public Cook() {
    }

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

    public void Work() {
        System.out.println("炒菜");
    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Manager m = new Manager("001", "张三", (double)10000.0F, (double)2000.0F);
        PrintStream var10000 = System.out;
        String var10001 = m.getId();
        var10000.println(var10001 + " " + m.getName() + " " + m.getSalary() + " " + m.getBouns());
        m.eat();
        m.Work();
        Cook c = new Cook();
        c.setId("002");
        c.setName("李四");
        c.setSalary((double)5000.0F);
        var10000 = System.out;
        var10001 = c.getId();
        var10000.println(var10001 + " " + c.getName() + " " + c.getSalary());
        c.eat();
        c.Work();
    }
}

练习二.带有继承结构的标准Javabean类
在黑马程序员中有很多员工(Employee),按照工作内容不同分教研部员工(Teacher)和行政部员工(AdminStaff)
1.教研部根据教学的方式不同又分为讲师(Lecturer)和助教(Tutor)
2.行政部根据负责事项不同,又分为维护专员(Maintainer),采购专(Buyer)
3.公司的每一个员工都编号,姓名和其负责的工作
4.每个员工都有工作的功能,但是具体的工作内容又不一样。

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

    public Employee() {
    }

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

    public String getId() {
        return this.id;
    }

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

    public String getName() {
        return this.name;
    }

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

    public void Work() {
        System.out.println("工作");
    }
}
public class AdminStaff extends Employee {
    public AdminStaff() {
    }

    public AdminStaff(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("行政部");
    }
}
public class Maintainer extends AdminStaff {
    public Maintainer() {
    }

    public Maintainer(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("维护");
    }
}
public class Buyer extends AdminStaff {
    public Buyer() {
    }

    public Buyer(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("采购");
    }
}
public class Lecturer extends Teacher {
    public Lecturer() {
    }

    public Lecturer(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("讲师");
    }
}
public class Teacher extends Employee {
    public Teacher() {
    }

    public Teacher(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("教研");
    }
}
public class Tutor extends Teacher {
    public Tutor() {
    }

    public Tutor(String id, String name) {
        super(id, name);
    }

    public void Work() {
        System.out.println("助教");
    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Lecturer l = new Lecturer("001", "张三");
        PrintStream var10000 = System.out;
        String var10001 = l.getId();
        var10000.println(var10001 + " " + l.getName());
        l.Work();
        System.out.println("--------------------------");
        Tutor t = new Tutor();
        t.setId("002");
        t.setName("李四");
        var10000 = System.out;
        var10001 = t.getId();
        var10000.println(var10001 + " " + t.getName());
        t.Work();
        System.out.println("--------------------------");
        Maintainer m = new Maintainer("003", "王五");
        var10000 = System.out;
        var10001 = m.getId();
        var10000.println(var10001 + " " + m.getName());
        m.Work();
        System.out.println("--------------------------");
        Buyer b = new Buyer();
        b.setId("004");
        b.setName("赵六");
        var10000 = System.out;
        var10001 = b.getId();
        var10000.println(var10001 + " " + b.getName());
        b.Work();
    }
}

三.多态

 1.什么是多态?
同类型的对象,表现出的不同形态。
2.多态的表现形式
父类类型 对象名称=子类对象;
3.多态的前提
(1).有继承关系
(2)有父类引用指向子类对象  Fu f= new Zi();
(3)有方法重写

4.多态的好处?
使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

5.多态调用成员的特点
变量调用:编译看左边,运行也看左边。
方法调用:编译看左边,运行看右边。

理解:调用成员变量:编译看左边,运行也看左边
编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。
运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
调用成员方法:编译看左边,运行看右边
编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。
运行看右边:java运行代码的时候,实际上运行的是子类中的方法。

6.多态调用成员的内存图解

 7.多态的优势
(1)在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
Person p=new student ();
p.work();//当业务逻辑发生改变时,后续代码无需修改
(2)定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

8.多态的弊端是什么?

不能使用子类的特有功能

怎么解决这一弊端呢?

使用instanceof关键字判断,然后使用强制类型转换。
9.引用数据类型的类型转换,有几种方式?
自动类型转换:Person p= new Student();

强制类型转换:Student s =(Student) p;

10.强制类型转换能解决什么问题?
可以转换成真正的子类类型,从而调用子类独有功能。
不能乱转,转换类型与真实对象类型不一致会报错
转换的时候用instanceof关键字进行判断

练习

public class Animal {
    private int age;
    private String color;
    private String something;

    public Animal() {
    }

    public Animal(int age, String color) {
        this.age = age;
        this.color = color;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return this.color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void eat(String something) {
    }
}
public class Cat extends Animal {
    public Cat() {
    }

    public Cat(int age, String color) {
        super(age, color);
    }

    public void catchMouse() {
        System.out.println("猫在抓老鼠");
    }
}
public class Dog extends Animal {
    public Dog() {
    }

    public Dog(int age, String color) {
        super(age, color);
    }

    public void lookHome() {
        System.out.println("狗子在看家");
    }
}
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 this.name;
    }

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

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void keepPet(Animal animal, String something) {
        if (animal instanceof Cat c) {
            something = "鱼";
            int var10001 = this.age;
            System.out.println("年龄为" + var10001 + "岁的" + this.name + "养了一只" + animal.getColor() + "颜色的" + animal.getAge() + "岁的猫");
            PrintStream var10000 = System.out;
            var10001 = animal.getAge();
            var10000.println(var10001 + "岁的" + animal.getColor() + "颜色的猫眯着眼睛侧着头吃" + something);
            c.catchMouse();
        } else if (animal instanceof Dog d) {
            something = "骨头";
            int var9 = this.age;
            System.out.println("年龄为" + var9 + "岁的" + this.name + "养了一只" + animal.getColor() + "颜色的" + animal.getAge() + "岁的狗");
            PrintStream var7 = System.out;
            var9 = animal.getAge();
            var7.println(var9 + "岁的" + animal.getColor() + "颜色的狗两只前腿死死抱住" + something + "猛吃");
            d.lookHome();
        }

    }
}
public class Test {
    public Test() {
    }

    public static void main(String[] args) {
        Person person = new Person("老王", 30);
        Animal dog = new Dog(2, "黑");
        person.keepPet(dog, "骨头");
        Person p2 = new Person("老李", 25);
        Animal cat = new Cat(3, "灰");
        p2.keepPet(cat, "鱼");
    }
}

四.包

(1)什么是包?
包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护。
(2)包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意。 例如:com.itheima.domain
package com.itheima.domain;
(3)全类名,全限定名:包名+类名,例如:com.itheima.domain. Student
(4)使用其他类的规则
1.使用其他类时,需要使用全类名。

 这样写太繁琐了,可以先导包,再使用

2.使用同一个包中的类时,不需要导包。
3.使用java.lang包中的类时,不需要导包,其他情况都需要导包。如使用String不需要导包
4.如果同时使用两个包中的同名类,需要用全类名。

五.final

(1).final:最终的,不可改变的

(2)修饰方法:表明该方法是最终方法,不能被重写
修饰类:表明该类是最终类,不能被继承
修饰变量:叫做常量,只能被赋值一次

(3)常量

1.常量:实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性。
2.常量的命名规范:单个单词:全部大写
多个单词:全部大写,单词之间用下划线隔开
3.细节:final修饰的变量是基本类型,那么变量存储的数据值就不能发生改变。
final修饰的变量是引用类型,那么变量存储的地址值不能发生改变,对象内部可以改变。

public class Test {
    public static void main(String[] args) {
           final int a=10;
          // a=20;//报错
            System.out.println(a);
    }}
class FU{
        public final void show(){//什么时候会用呢?
            //当方法是一种规则,我们不希望别人改变它时,会用
            System.out.println("父类的show方法");
        }
    }
class Zi extends FU{
    //public void show(){//会报错
     //   System.out.println("子类的show方法");
   // }
}

 

public class Test {
    public static void main(String[] args) {
        final int a=10;
        System.out.println(a);
        //a=20;报错
        //final修饰基本数据类型:记录的值不能改变
        //final修饰引用数据类型:记录的地址值不会改变,内部的属性值还是可以改变
        final Student s=new Student("张三",20);
        //s=new Student();会报错,地址值不能改变
        s.setName("李四");
        s.setAge(30);//不会报错,属性值可以改变
        System.out.println(s.getName()+":"+s.getAge());
        //数组也是引用数据类型
        final int []arr={1,2,3};
        //arr=new int[10];报错
        arr[0]=4;
        arr[1]=5;
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
            //核心:常量记录的数据是不能发生改变的
        }
    }
}
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;
    }
}

练习

常量的练习

将学生管理系统中用户的操作改写为常量的形式

六.权限修饰符

1.权限修饰符是用来控制一个成员能够被访问的范围的,可以修饰成员变量,方法,构造方法,内部类。

2.权限修饰符的分类

private,默认,protected,public

3.四种作用范围由小到大: private <空着不写< protected <public 

 4.权限修饰符的使用规则

实际开发中,一般只用private和public

成员变量私有

方法公开

特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有,例如ArrayList中add方法中的grow方法。

七.代码块

1.代码块的分类:

局部代码块

构造代码块:1.写在成员位置的代码块

2.作用:可以把多个构造方法中重复的代码抽取出来

3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法

静态代码块:

格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候,做一些数据初始化的时候使用。

2.代码块的作用

局部代码块:

提前结束变量的生命周期(已淘汰)

构造代码块的作用:

抽取构造方法中的重复代码(不够灵活】

静态代码块的作用:

数据的初始化(重点)

八.抽象

1.分类:抽象方法和抽象类

2.概念:

抽象方法:将共性的行为(方法)抽取到父类之后,由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体,该方法就可以定义为抽象方法。
抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类

3.抽象类和抽象方法的定义格式
抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
抽象类的定义格式:
public abstract class 类名{}

4.抽象类和抽象方法的注意事项

(1)抽象类不能实例化
(2)抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
(3)可以有构造方法
(4)抽象类的子类:要么重写抽象类中的所有抽象方法,要么是抽象类

5.意义:使子类形式统一

练习.编写带有抽象类的标准Javabean类
青蛙frog   属性:名字,年龄
行为:吃虫子,喝水
狗Dog  属性:名字,年龄
行为:吃骨头,喝水
山羊Sheep  属性:名字,年龄
行为:吃草,喝水

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 void drink(){
        System.out.println("喝水中,勿扰。。。");
    }
    public abstract void eat();
}
public class Dog extends Animal{
    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat(){
        System.out.println("吃骨头");
    }
}
public class Frog extends Animal{
    public Frog() {
    }

    public Frog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat(){
        System.out.println("吃虫子");
    }
}
public class Sheep extends Animal{
    public Sheep() {
    }

    public Sheep(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat(){
        System.out.println("吃草");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal a=new Dog();
        d(a);//多态仍然能使用
        Frog f=new Frog();
        f.eat();
        f.drink();
        Dog d=new Dog();
        d.eat();
        d.drink();
        Sheep sheep=new Sheep();
        sheep.eat();
        sheep.drink();
    }
    public static void d(Animal a){
        a.eat();
    }

}

九.接口

1.为什么要接口:接口是一种规则,是对行为的抽象,不是所有子类共有的属性,而是某几个子类共有的。

2.接口的定义和使用
接口用关键字interface来定义
public interface 接口名{}
接口不能实例化
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名{}
接口的子类(实现类):
要么重写接口中的所有抽象方法
要么是抽象类

3.注意
注意1:接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements 接口名1,接口名2{
注意2:实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements 接口名1,接口名2

练习:编写带有接口和抽象类的标准Javabean类
青蛙:属性:名字,年龄
行为:吃虫子,蛙泳
狗:属性:名字,年龄
行为:吃骨头,狗刨
兔子:属性:名字,年龄
行为:吃胡萝卜


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 void drink(){
        System.out.println("喝水中,勿扰。。。");
    }
    public abstract void eat();
}
public interface swim {
    public void swimming();
}

public class Dog extends Animal implements swim {
    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("吃骨头");
    }
    public void swimming(){
        System.out.println("狗刨");
    }
}
public class Frog extends Animal implements swim {
    public Frog() {
    }

    public Frog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("吃虫子");
    }
    public void swimming(){
        System.out.println("蛙泳");
    }
}
public class Rabbit extends Animal{
    public Rabbit() {
    }

    public Rabbit(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("吃胡萝卜");
    }
}
public class Test {
    public static void main(String[] args) {
        Frog f= new Frog();
        f.eat();
        f.swimming();
        Dog d= new Dog();
        d.eat();
        d.swimming();
        Rabbit r= new Rabbit();
        r.eat();
    }
}

4.接口中成员的特点
成员变量:只能是常量
                默认修饰符:public static final 
构造方法:没有
成员方法:只能是抽象方法
默认修饰符:public abstract
JDK7以前:接口中只能定义抽象方法。
JDK8的新特性:接口中可以定义有方法体的方法。
JDK9的新特性:接口中可以定义私有方法。

5.接口和类之间的关系
类和类的关系:继承关系,只能单继承,不能多继承,但是可以多层继承
类和接口的关系:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
接口和接口的关系:继承关系,可以单继承,也可以多继承

练习:编写带有接口和抽象类的标准Javabean类
我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。
为了出国交流,跟乒乓球相关的人员都需要学习英语。
请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口?
乒乓球运动员:姓名,年龄,学打乒乓球,说英语
篮球运动员:姓名,年龄,学打篮球
乒乓球教练:姓名,年龄,教打乒乓球,说英语
篮球教练:姓名,年龄,教打篮球

public interface interEnglish {
    public abstract void speakEnglish();
}
//将人定义为abstract,因为我不想让外界直接创建人的对象
//因为此时直接创建人的对象是没有意义的
public abstract 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;
    }
}
public abstract class Students extends person{
    public Students() {}
    public Students(String name , int age) {
        super(name, age);
    }
    public abstract void Study();

}
public abstract class Coach extends person {
    public Coach() {
    }
    public Coach(String name, int age) {
        super(name, age);
    }
    public abstract void teach();
}
public class baskerballCoach extends Coach{
    public baskerballCoach() {
    }

    public baskerballCoach(String name, int age) {
        super(name, age);
    }
    @Override
    public void teach(){
        System.out.println("教打篮球");
    }
}
public class basketballStudents extends Students{
    public basketballStudents() {}
    public basketballStudents(String name, int age) {
        super(name, age);
    }
    @Override
    public void Study(){
        System.out.println("学打篮球");
    }
}
public class tabletennisCoach extends Coach implements interEnglish{
    public tabletennisCoach(){
    }
    public tabletennisCoach(String name, int age){
        super(name, age);
    }
    @Override
    public void teach(){
        System.out.println("教打乒乓球");
    }
    @Override
    public void speakEnglish(){
        System.out.println("说英语");
    }
}
public class tabletennisStudent extends Students implements interEnglish {
    public tabletennisStudent() {
    }

    public tabletennisStudent(String name, int age) {
        super(name, age);
    }
    @Override
    public void Study(){
        System.out.println("学打乒乓球");
    }
    @Override
    public void speakEnglish(){
        System.out.println("说英语");
    }
}
public class Test {
    public static void main(String[] args) {
        tabletennisStudent ts=new tabletennisStudent("张三",20);
        tabletennisCoach tc=new tabletennisCoach("李四",30);
        basketballStudents bs=new basketballStudents("王五",25);
        baskerballCoach bc=new baskerballCoach("赵六",35);
        ts.Study();
        ts.speakEnglish();
        System.out.println(ts.getName()+" "+ts.getAge());
        tc.teach();
        tc.speakEnglish();
        System.out.println(tc.getName()+" "+tc.getAge());
        bs.Study();
        System.out.println(bs.getName()+" "+bs.getAge());
        bc.teach();
        System.out.println(bc.getName()+" "+bc.getAge());
    }
}

 6.JDK8以后接口中新增的方法
(1)允许在接口中定义默认方法,需要使用关键字 default 修饰
作用:解决接口升级的问题
接口中默认方法的定义格式:格式:public default 返回值类型方法名(参数列表){}
范例:public default void show(){ }
接口中默认方法的注意事项:默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字。public可以省略,default不能省略
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写

(2)允许在接口中定义定义静态方法,需要用static修饰
接口中静态方法的定义格式:
格式:public static 返回值类型方法名(参数列表){ }
范例:public static void show(){}
接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略

7.JDK9新增的方法
接口中私有方法的定义格式:
格式:private 返回值类型方法名(参数列表){}
范例1:private void show(){}
格式2:private static 返回值类型方法名(参数列表){}
范例2:private static void method(){}

8.接口的应用

(1)接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
(2)当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。

十.适配器设计模式

1.概念:设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
2.目的:使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
3.简单理解:设计模式就是各种套路。
4.适配器设计模式:解决接口与接口实现类之间的矛盾问题

5.什么时候用:当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器设计模式
6.书写步骤:编写中间类XXXAdapter实现对应的接口,对接口中的抽象方法进行空实现,让真正的实现类继承中间类,并重写需要用的方法,为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰。

 

十一.内部类

类的五大成员:属性、方法、构造方法、代码块、内部类

1.什么是内部类?
在一个类的里面,再定义一个类。
举例:在A类的内部定义B类, B类就被称为内部类

 2.什么时候用到内部类?
B类表示的事物是A类的一部分,且B单独存在没有意义。
比如:汽车的发动机,ArrayList的迭代器,人的心脏等等

3.内部类的访问特点
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象

public class Car {
    String Name;
    int age;
    public void show(){
        System.out.println("Name: " + Name);
        System.out.println("Age: " + age);
        //System.out.println(engineName);报错,外部类无法直接访问内部类
        Engine e=new Engine();
        System.out.println(e.engineName);
    }
    class Engine{
        String engineName;
        int engineAge;
        public void shaow(){
            System.out.println("Engine: " + engineName);
            System.out.println("Engine: " + engineAge);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Car c=new Car();
        c.Name="兰博基尼";
        c.age=2;
        c.show();
    }
}

4.内部类的分类:
成员内部类,静态内部类,局部内部类,匿名内部类。

5.成员内部类:写在成员位置的,属于外部类的成员。
成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等。
在成员内部类里面,JDK16之前不能定义静态变量,JDK 16开始才可以定义静态变量。


6.获取成员内部类对象的两种方式?
方式一:当成员内部类被private修饰时,在外部类编写方法,对外提供内部类对象
方式二:当成员内部类被非私有修饰时,直接创建对象。
Outer.Inner oi = new Outer().new Inner();
7.外部类成员变量和内部类成员变量重名时,在内部类如何访问?
System.out.println(Outer.this.变量名);

 

8.静态内部类
静态内部类是一种特殊的成员内部类,静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
创建静态内部类对象的格式:外部类名.内部类名 对象名= new 外部类名.内部类名();


调用非静态方法的格式:先创建对象,用对象调用

调用静态方法的格式:外部类名.内部类名.方法名();

9.局部内部类
(1)将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
(2)外界是无法直接使用,需要在方法内部创建对象并使用。
(3)该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

10.匿名内部类
匿名内部类本质上就是隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。

格式的细节:包含了继承或实现,方法重写,创建对象。整体就是一个类的子类对象或者接口的实现类对象
使用场景:当方法的参数是接口或者类时,以接口为例,可以传递这个接口的实现类对象,如果实现类只要使用一次,就可以用匿名内部类简化代码。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值