Java基础08:面向对象进阶(上)
- 一、static
- 1. 静态变量
- 2. 静态方法
- 3. 工具类
- 4. static注意事项
- 5. 重新认识main方法
 
- 二、继承
- 1. 继承的概念
- 2. 继承的特点
- 3. 继承中访问成员变量
- 4. 继承中访问成员方法(方法重写)
- 5. 继承中访问构造方法
 
- 三、多态
- 1. 多态的概念
- a. 多态的优势和弊端
- b. 类型转换
- c. 多态举例
 
- 2. 多态调用成员的特点
 
- 四、包、final、权限修饰符、代码块
- 1. 包
- 2. final
- a. 常量
 
- 3. 权限修饰符
- 4. 代码块
 
一、static
- static表示静态,是java中的一个修饰符,可以修饰成员方法、成员变量。
1. 静态变量
-  被static修饰的成员变量,叫做静态变量。 
  
-  特点 - 被该类所有对象共享;
- 不属于对象,属于类;
- 随着类的加载而加载,优先于对象存在。
 
-  调用方法 -  类名调用(推荐) 
  
-  对象名调用 
 
-  
2. 静态方法
- 特点 
  - 多用在测试类和工具类中
- JavaBean类中很少使用
 
- 调用方式 
  - 类名调用(推荐)
- 对象名调用
 
3. 工具类
- static多用于工具类中。
- 特点 
  - 类名见名知意
- 私有化构造方法
- 方法定义为静态
 
| 类 | 描述 | 
|---|---|
| JavaBean类 | 用来描述一类事物的类。比如Student、Cat等 | 
| 测试类 | 用来检查其他类是否书写正确,带有main方法的类,是程序的入口 | 
| 工具类 | 帮助我们做一些事情,但是不描述任何事物的类 | 
4. static注意事项
- 静态方法只能访问静态变量和静态方法。
- 非静态方法可以访问静态变量或静态方法,也可以访问非静态的成员变量和非静态的成员方法。
- 静态方法中没有this关键字。
概括:
静态方法中,只能访问静态。
非静态方法可以访问所有。
静态方法没有this关键字。
5. 重新认识main方法
public class HelloWorld {
	public static void main(String[] args){
		...
	}
}
- public : 被JVM调用,访问权限足够大。
- static : 被JVM调用,不用创建对象,直接类名访问。因为main方法是静态的,所以测试类中其他方法也需要是静态的。
- void : 被JVM调用,不需要给JVM返回值。
- main : 一个通用的名称,虽然不是关键字,但是被JVM识别。
- String [] args : 以前用于接受键盘录入数据,现在没用。
二、继承
1. 继承的概念
- 继承是面向对象三大特征之一,可以让类与类之间产生父子关系。
- 当类与类之间,存在相同的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码。
- 继承的格式:public class 子类 extends 父类 {}
2. 继承的特点
- Java只支持单继承,不支持多继承,但支持多层继承。
- 每一个类都直接或间接的继承于Object。
- 子类只能访问父类中非私有的成员。
3. 继承中访问成员变量
- this调用:就近原则。
- super调用:直接找父类。
System.out.println(name);  // 从局部位置开始往上找
System.out.println(this.name);  // 从本类成员位置开始往上找
System.out.println(super.name);  // 从父类成员位置开始往上找
4. 继承中访问成员方法(方法重写)
- 方法的概念:
 在继承体系中,子类出现了和父类中一模一样的方法声明,就称自类的这个方法是重写的方法。
- 在重写方法时都加上@Override注解,代码安全。
- 子类重写的方法尽量和父类的方法保持一致。
- 只有虚方法表里面的方法可以被重写。
5. 继承中访问构造方法
- 子类不能继承父类的构造方法,但是可以通过super调用。
- 自类构造方法的第一行,有一个默认的super():
- 默认先访问父类中无参的构造方法,再执行自己。
- 如果想要调用父类有参构造,必须手动书写。
三、多态
1. 多态的概念
- 意思是对象的多种形态。
- 多态的前提 
  - 有继承/实现关系
- 有父类引用指向子类对象
- 有方法的重写
 
a. 多态的优势和弊端
- 多态的好处 
  - 在多态形式下,对象可以实现解耦合,便于扩展和维护。
- 使用父类型作为参数,可以接受所有子类对象。体现多态的扩展性和便利。
 
- 多态的弊端 
  - 不能使用子类的特有功能。
 
b. 类型转换
- 自动类型转换 Person p = new Student();
- 强制类型转换 Student s = (Student)p;
- 强制类型转换能解决什么问题: 
  - 可以转换成真正的子类类型,从而调用子类独有功能。
- 转换类型与真实对象类型不一致会报错。
- 转换的时候用instanceof关键字进行判断。
 
c. 多态举例
人类
package day13.polymorphismDemo1;
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;
    }
    public void show(){
        System.out.println(name + ", " + age);
    }
}
学生类,重写父类的show方法。
package day13.polymorphismDemo1;
public class Student extends Person {
    @Override
    public void show() {
        System.out.println("学生的信息为:" + getName() + ", " + getAge());
    }
}
教师类,重写父类的show方法。
package day13.polymorphismDemo1;
public class Teacher extends Person {
    @Override
    public void show() {
        System.out.println("老师的信息为:" + getName() + ", " + getAge());
    }
}
测试类,用父类作为参数接收学生类和教师类。
package day13.polymorphismDemo1;
public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("zhangsan");
        student.setAge(12);
        Teacher teacher = new Teacher();
        teacher.setName("lisi");
        teacher.setAge(14);
        register(student);
        register(teacher);
    }
    public static void register(Person person) {
        person.show();
    }
}
输出结果
 
2. 多态调用成员的特点
- 变量调用:编译看左边,运行也看左边,
- 方法调用:编译看左边,运行看右边。
// 多态方式创建对象
Animal animal = new Dog();
// 成员变量
// 编译时,如果左边的父类(Animal)中没有name变量,则编译失败
// 运行时,实际获取的是父类(Animal)中name的值
sout(animal.name);
// 成员方法
// 编译时,如果左边的父类中(Animal)中没有show方法,则编译失败
// 运行时,实际调用的是右边子类(Dog)中的show方法【重写】
animal.show();
四、包、final、权限修饰符、代码块
1. 包
- 包的作用: 
  - 包就是文件夹,用来管理各种不同功能的Java类。
 
- 包名书写规则: 
  - 域名反写+包的作用
- 需要全部小写,见名知意
 
- 全类名: 
  - 包名 + 类名
 
- 什么时候需要导包? 
  - 使用同一个包中的类时,不需要导包。
- 使用java.lang包中的类时,不需要导包。
- 其他情况都需要导包
- 如果同时使用两个包中的同类名,需要用全类名。
 
package day13.apackage.demo1;
import day13.apackage.demo2.Teacher;
public class Test {
    public static void main(String[] args) {
        Student student = new Student();  // 同一个包中的类
        String s = "";  // java.lang
        
        // 其他包的类需要导包,相同包名用全类名
        Teacher teacher = new Teacher();  
        day13.apackage.demo3.Teacher teacher1 = new day13.apackage.demo3.Teacher();  
    }
}
2. final
- final 修饰方法:表明该方法是最终方法,不能被重写。
- final 修饰类:表明该类是最终类,不能被 继承。
- final 修饰变量:叫做常量,只能被赋值一次。
a. 常量
- 常量一般作为系统的配置信息,方便维护,提高可读性。
- 命名规范:单词全部大写,单词之间用下划线隔开 。
- 基本类型常量:数据值不能改变。
- 引用类型常量:地址值不能改变,对象内部的可以改变。
3. 权限修饰符
- 用来控制一个成员能够被访问的范围。
- 可以修饰成员变量、方法、构造方法、内部类。
- 分类:有四种作用范围由小到大(private<空着不写<protected<public)
| 修饰符 | 同一个类中 | 同一个包中其他类 | 不同包下的子类 | 不同包下的无关类 | 
|---|---|---|---|---|
| private | ✓ | |||
| 空着不写 | ✓ | ✓ | ||
| protected | ✓ | ✓ | ✓ | |
| public | ✓ | ✓ | ✓ | ✓ | 
- 实际开发中,一般只用private和public 
  - 成员变量私有
- 方法公开
- 如果方法中的代码是抽取其他方法里共性代码,这个方法一般也私有。
 
4. 代码块
- 代码块分类:局部代码块、构造代码块、静态代码块。
- 局部代码块:提前结束变量的生命周期(已淘汰)。
- 构造代码块(不够灵活): 
  - 写在成员位置;
- 可以把多个构造方法中重复的代码抽取出来;
- 构造代码块优先于构造方法执行。
 
- 静态代码块(重点): 
  - 格式:static {}
- 特点:随着类的加载而加载,并且自动触发,只执行一次
- 使用场景:数据初始化。
 


















