【JavaLearn】 # (3)static关键字、package/import、注释、封装性、继承性

1. static关键字

一个类的成员包括变量方法构造方法代码块内部类。static 可以修饰除了构造方法以外的所有成员。

使用 static 修饰的成员是静态成员,属于某个类的,一个类只有一份,不使用 static 修饰的成员为实例成员属于类的每个对象,被所有的对象共享

1.1 static 变量

  • 非静态方法可以访问静态变量、非静态变量
  • 静态方法只能访问静态变量
public class Student {
    int sno;
    String name;
    int age;
    String cup; // 水杯

    // 使用static修饰后,整个类只有这一个
    static String waterMachine; // 饮水机

    // 默认构造方法
    public Student() {

    }

    // 【【重载】】构造方法
    public Student(int sno, String name) {
        this.sno = sno;   // 1. 调用成员变量
        this.name = name;
    }

    public Student(int sno, String name, int age) {
        this(sno, name);  // 2. 调用构造方法
    }

    public void show() {
        System.out.println("My name is " + name);
    }

    public void study() {
        this.show();  // 3. 调用成员方法
        System.out.println("good good study!");
    }

    public static void main(String[] args) {
        System.out.println(Student.waterMachine); // null

        Student stu = new Student();
        stu.waterMachine = "海尔饮水机";
        System.out.println(Student.waterMachine); // 海尔饮水机

        Student stu1 = new Student(2, "李四");
        System.out.println(Student.waterMachine);
    }
}

static 变量和非 static 变量的区别:

  • 份数不同:静态变量 ==》 一个类 1 份, 非静态变量 ==》 一个对象 1 份
  • 存储位置不同:静态变量 ==》 方法区 , 非静态变量 ==》 堆内存
  • 内存分配空间的时间不同:静态变量 ==》 第一次加载类的时候, 非静态变量 ==》 创建对象的时候
  • 生命周期不同:静态变量 ==》 和类的生命周期相同, 非静态变量 ==》 和所属对象相同
  • 调用方法不同:静态变量 ==》 通过**类名(推荐)**或对象名调用, 非静态变量 ==》 只能通过对象名调用

1.2 static方法

  • 只能访问 static 变量和 static 方法
  • 通过类名调用

理解:加载类的时候就加载静态变量静态方法,此时可能还没有创建对象,所以非静态变量和方法还没有分配空间,无法访问。

private static String name;
public static void show() {
    System.out.println(Student.name);
}

1.3 static 代码块

局部代码块(成员)代码块static代码块
位置方法中类中类中
数量多个多个多个
执行顺序依次执行依次执行依次执行
作用局部代码块中定义的变量作用范围只限于当前代码块每次创建对象的时候都执行;先执行代码块,再执行构造方法实际开发中很少用,可以将各个构造方法中公共的代码提取到代码块;匿名内部类不能提供构造方法,此时初始化操作U;放到代码块中第一次加载类的时候执行,最先执行只执行一次。给静态变量赋初始值,一般用于执行一些全局性的初始化操作(创建工厂、加载数据库初始信息)

2. package 包和 import 导入

2.1 package关键字

使用包的作用:

  • 解决类重名的问题
  • 还和访问权限有关系

定义包:

  • 域名倒写:com.lwclick.包名
  • 通常是类的第一句非注释性语句

Java常用包:

  • java.lang:无需导入直接用的类,Java的核心类,如 String、Math、Integer、System、Thread
  • java.util:一些实用的工具类,如定义系统特性、使用与日期日历相关的函数
  • java.io:包含多种输入/输出功能的类
  • java.net:包含与网络相关的操作的类

2.2 import关键字

  • 使用其他包的类,需要使用import进行导入,从而可以在本类中直接使用类名进行操作。

  • 导入时,可以使用通配符 *,访问包下所有的类。
    java.util.*只能访问 util 下所有的类,不能直接访问 java.util.concurrent.下面的类)

  • 如果想导入两个同名的类,其中一个使用 import 进行导入,另一个使用全限定类名(包名+类名)进行导入

静态导入

import staticjava.lang.Math.*; 导入的不是类或接口,而是静态的方法和静态的属性(JDK1.5之后)

静态导入后,在本类可以直接使用静态的方法或者属性。

3. 文档注释

/**
 * 注释文字
 */

养成良好习惯,在类,方法,属性前面加文档注释,然后就可以使用 IDEA 快捷的导出API

步骤:Tools ==》 Generate JavaDoc… ==》 根据需求自己配置参数,在 Other command line arguments 一栏里输入:-encoding utf-8用来调整编码格式

4. 封装性

面向对象的三大特征之一,例如电视机,我们只需要知道如何使用它暴露的接口(比如电源开关)即可,不需要知道内部的各种细节。

封装追求的就是“高内聚,低耦合”,高内聚是类中的功能关系密切,数据的操作细节由自己完成,不允许外部干涉,低耦合是仅暴露少量的方法给外部使用。

同一个类同一个包中的类子类所有包的所有类
private*
default(默认)**
protected***(其他包中该类的子类)
public****

规范:

  • 将类的属性全都设为私有(private)的,然后向外暴露 public 的 getter / setter方法(可以在其中加入逻辑判断)
  • 一些只用于本类的辅助性方法可以用 private 修饰,希望其他类调用的方法用 public 修饰
public class Student {
    // 使用private封装成员属性
    private int sno;
    private String name;

    public Student() {

    }

    public Student(int sno, String name) {
        // 直接调用本类封装好的方法,复用代码
        this.setSno(sno);
        this.setName(name);
    }

    // 暴露给外部public声明的操作属性的方法
    public int getSno() {
        // 其内可以添加if判断
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length() > 4) {
            this.name = name.substring(0, 4);
            return;
        }
        this.name = name;
    }
}

class TestStu {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("张三张三张三");
        System.out.println(stu.getName());
    }
}

5. 继承性

面向对象编程的三大特征之一,让我们更加容易实现对于已有类的扩展(子类可以从父类那里继承变量和方法),实现代码的重用。

父类 Animal

public class Animal { // 没有明确写出继承关系,那么就是继承了 Object
    private String color;
    private int age;
    public String testFiled;

    public Animal() {

    }

    public Animal(String color, int age) {
        super(); // 不写也是默认存在的,调用 Object类的构造方法
        this.color = color;
        this.age = age;
    }

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

    public void sleep() {
        System.out.println("-------- sleep() --------");
    }
}

子类 Dog

public class Dog extends Animal{

    // 父类使用private修饰的成员变量,虽然可以继承,但是不可以直接访问,需要使用 super 关键字
    private String nickName; // 昵称,子类自己的成员变量

    public Dog() {

    }

    public Dog(String color, int age, String nickName) {
        super(color, age); // 调用父类的构造函数
        // super.testFiled;  调用父类 public 或者 protected 修饰的成员变量
        // super.sleep();    调用父类 public 修饰的成员方法
        this.nickName = nickName;
    }

    public void guard() {
        System.out.println("Dog guard.....");
    }

    /**
     * 父类的方法无法满足子类的需求
     * 【【重写】】父类的方法
     */
    @Override
    public void eat() {
        System.out.println("------ Dog eat() ---------");
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog("褐色", 3, "旺财");
        dog.eat(); // 调用自己重写的 eat 方法
        dog.sleep(); // 调用父类的 sleep 方法
    }
}

继承使用要点:

  • 父类:超类,基类, 子类:派生类
  • Java只有单继承
  • 子类继承父亲,可以得到父类的全部属性和方法(除了构造方法),但不一定能直接访问
  • 如果定义一个类时,没有调用 extends,则它的父类是:java.lang.Object

重写与重载

  • 总体的区别:解决的问题不同,即作用不用

    • 重载 overload:同一个类中,在一个类里面为一种行为提供多种实现方式并提高可读性
    • 重写 override:子类和父类间,父类无法满足子类的要求,子类通过方法重写满足要求
  • 细节的区别:

    • 重载,只要方法名相同参数不同即可,与修饰符、返回值、抛出异常都无关
    • 重写,要求在方法名相同,参数相同的基础上,
      • 修饰符: 子类 >= 父类
      • 返回值: 子类 <= 父类
      • 抛出的异常:子类 <= 父类
  • 扩展:

    • 方法使用 final 修饰,无法被重写
    • 静态方法无法进行方法重写。父类中有一个的 static 方法,且在子类中有个完全相同的静态方法,那么该子类实际上只是将父类中的同名方法进行了隐藏,而非重写。添加 @Override 注解将会报错

5.1 成员变量的隐藏

如果父类和子类有同名的成员变量,不存在变量的重写,分别占有自己的空间子类的成员变量优先

父类 Animal

public class Animal {
    protected String color = "Animal color";
    private int age;
}

子类 Dog

public class Dog extends Animal{

    private String nickName; // 昵称
    private String color = "Dog color";

    public void getColor() {
        System.out.println(color);       // 调用的是自己的color     ==>    Dog color
        System.out.println(this.color);  // 调用自己的color         ==>    Dog color
        System.out.println(super.color); // 调用父类的color         ==>    Animal color
        String color = "local color";
        System.out.println(color);      // 调用的是局部变量color     ==>    local color
    }
}

5.2 构造方法的执行顺序

  • 在子类的构造方法里,第一句默认是 super(),调用父类无参数的构造方法,所以先执行父类的构造方法
  • 在子类的构造方法里,第一条语句也可以显式的指定父类有参数的构造方法 super(…)
  • 也可以显式的指定为当前类的构造方法 this(…)

注意事项

  • 每个类最好要提供无参数的构造方法
  • 构造方法的第一条语句,可以使用 super 或者 this 调用构造方法
  • 构造方法中,不能同时使用 super 和 this
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LRcoding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值