java基础之面向对象基础进阶day01

发布时间:2024年01月22日

static关键字

????????static是一个修饰符,表示静态的意思,可以修饰属性、方法、代码块。它的主要作用是使得这些语法结构不再与对象实例相关,而是属于类本身,从而可以在不创建对象的情况下进行访问和调用。?

?静态成员

?????????static修饰类中的数据成员,该成员就成了静态数据成员,也称为类成员;类成员,是属于类的,为这个类所有对象共享,只占用一块内存空间。它们的值可以被所有对象共享。静态变量在类加载时就已经被初始化,而且只会被初始化一次,直到程序结束或类被卸载。

static成员特点:?
  • 被类的所有对象共享。
  • 随着类的加载而加载,先于对象存在。
  • 对象需要类被加载后,才能被创建出来。
  • 可以通过类名调用,也可以通过对象名调用,推荐使用类名调用格式: 类名.静态数据成员;
  • 方法区中有一块专门的区域:静态区,专门用来存储类的static成员。
静态成员访问方式:?
class Student {
    public static int num;
}
public static void main(String[] args) {
    //可以使用类名来访问,推荐用法
    Student.num = 10;
    Student stu = new Student();
    //也可以对象来访问,但不推荐
    stu.num = 20;
}
?静态数据成员是属于类的,并且为这个类所有对象共享
package 包名;

/**
 * @author 谭梦寻
 * @version 1.1
 */
class Demo {
    public static int num;
}
public class TestStatic {

    public static void main(String[] args) {
    //1.静态数据成员会随着类的加载而加载(开辟内存并进行默认初始化)
    //先于对象存在
        Demo.num = 10;
    //2.实例化两个对象,然后通过对象访问静态成员,输出其值
        Demo demo1 = new Demo();
        Demo demo2 = new Demo();
        System.out.println(demo1.num);//输出结果为 10
        System.out.println(demo2.num);//输出结果为 10

/*  可以看出,无论是使用类访问静态属性,还是使用这个类的某个对象访问静属性,
    效果是一样的,这个属性对这个类的所有对象都是可见的、共享的。
    静态属性的存储位置:
        在方法区中有一块静态区,专门用来存储各个类静态数据成员。
        当操作静态数据成员时,不论是通过类名,还是通过对象名操作,
        都是操作静态区中对应的内存区域。
*/
    //3.通过类名修改静态成员值,再借助对象.static成员,输出其值
        Demo.num = 20;
        System.out.println(demo1.num);//输出结果为 20
        System.out.println(demo2.num);//输出结果为 20
    //4.通过对象名修改静态成员值,再借助类名.static成员,输出其值
        demo1.num = 30;
        System.out.println(Demo.num);//输出结果为 30
        System.out.println(demo2.num);//输出结果为 30
    }
}
静态属性的存储位置:?

在方法区中有一块静态区,专门用来存储各个类静态数据成员。当操作静态数据成员时,不论是通过类名,还是通过对象名操作,都是操作静态区中对应的内存区域?。

静态方法?

????????在类中,使用static修饰的方法,就是静态方法。和静态变量一样,静态方法属于类本身,而不是对象实例。因此,静态方法可以直接通过类名来调用,而不需要先创建一个对象。
????????static方法的作用,主要是用来操作static成员;

静态方法案例:?
class Demo {
    public static int num;
    public static void method() {
        System.out.println("这是一个静态方法");
    }
}
public class TestStatic {

    public static void main(String[] args) {
    //1.静态方法会随着类的加载而加载(开辟内存并进行默认初始化)
    //先于对象存在
        Demo.method();

        Demo.num = 10;
    //2.实例化对象,然后通过对象访问静态方法
        Demo demo1 = new Demo();
        demo1.method();
     //两者执行的结果是一样的


    }
}
static方法和普通成员方法区别:?
  • 静态方法只能访问静态的成员(因为静态先加载,非静态后加载,所以找不到非静态的内存空间地址)
  • 非静态方法可以访问静态的成员,也可以访问非静态的成员
  • 静态方法中是没有this关键字 (本质区别)?

案例:?

//学校类
class School {
    private String name; //名称
    private int num; //师生数量
    //用private修饰static成员,则该类外无法直接访问该static成员
    private static String library = "栋梁图书馆";
    //定义public修饰的static方法,专门来操作static成员
    public static String getLibrary() {
        //注意1:static方法中没有this
        //return this.library; //error
        //注意2:static方法中不可以访问普通数据成员
        //name = "一高"; //error
        return library;
    }
}
    //测试方法
public static void main(String[] args) {
    //1.在创建School对象前,输出 static成员值
    //编译报错,library为private,只能School类内访问
    //System.out.println(School.library);
    //2.借助类名调用static方法,推荐用法
    String lib = School.getLibrary();
    System.out.println(lib);
    //3.借助方法名调用static方法,不推荐
    School s1 = new School("第一中学",3000);
    System.out.println(s1.getLibrary());
}

代码块?

????????在Java中,使用 { } 括起来的代码被称为代码块,具体可以分为以下三类:

  • 局部代码块
  • 构造代码块
  • 静态代码块?
?局部代码块
  • 位置:在类的方法中定义
  • 格式:{ 语句体 }
  • 作用:用于限定变量的生命周期,使其尽早释放,从而提高占空间内存利用率

?案例:

public class Test0104_LocalBlock {

    public static void main(String[] args) {
    //局部代码块
    {
        int a = 10;
        System.out.println(a);
    }
    //上面局部代码块中的a是局部变量,遇到 } 其占用的内存空间就销毁了
    //下面输出语句编译报错
    //System.out.println(a);
    }
}
?构造代码块
  • 位置:类中方法外
  • 格式: { 语句体; }
  • 特点:每次构造方法执行前,都会先执行该代码块中代码
  • 作用:如果多个构造方法中出现相同代码,可抽取到该块中,从而提高代码复用性?。

案例:?

package com.briup.day07;

/**
 * @author 谭梦寻
 * @version 1.1
 */
public class TestConsBlock { //测试类
    public static void main(String[] args) {
//实例化2个对象,观察程序输出效果:
//每次构造方法执行前,都会自动执行构造代码块
        Module m1 = new Module();
        Module m2 = new Module(10);
    }
}

//基础类
class Module {
    private int num;

    //构造|匿名代码块
    {
        System.out.println("构造代码块: 构造方法执行前执行...");
    }

    //无参构造方法
    public Module() {
        System.out.println("Module() ...");
    }

    //有参构造方法
    public Module(int num) {
        System.out.println("Module(int) ...");
        this.num = num;
    }
}

静态代码块?
  • 位置:类中方法外
  • 格式: static { 语句体; }
  • 特点:需要通过static关键字修饰,随着类的加载而加载,只执行一次
  • 作用:类加载时做一些数据的初始化操作(一般给static成员赋值)?

案例:

class Teacher {
    //    属性
    private int id;
    //    静态属性
    private static String school;

    //    代码块
    static {
//    静态代码块
        school = "希望小学";
        System.out.println(school);//输出 希望小学
    }

    {
//       非静态代码块
        this.salary = 3000;
    }
}

类的加载时机?

?????????加载类的含义:JVM虚拟机将该类的class文件加载到内存的方法区中。
????????当Java代码中用到某个类的时候,就会加载该类。

?执行顺序: ? ?
  • 先静态后动态 ? ?
  • 先代码块 后构造器 ? ?
  • 先默认赋值 后显式赋值 ? ?
  • 属性显式赋值和代码顺序由位置决定

?案例:基础类


public class School {
        private String name;
        private static String library = "辽东图书馆";
        private int num;

    {
//        没有名字的代码块 只能创建对象时 自动调用
//        构造(创建对象)代码块 构造器 构造方法
        System.out.println("构造代码块");
    }
    static {
//        静态代码块只加载一次:类加载只加载一次 jvm机只需要一次将该类加载
        System.out.println("静态代码块");
//        this不能放在静态代码块中
//        创建对象
//        School school = new School();//可以
    }
    public School() {
    }

    public School(String name, int num) {
        this.name = name;
        this.num = num;
    }

    public String getName() {
        return name;
    }

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

    public  String getLibrary() {
        return library;
    }

    public void setLibrary(String library) {
        School.library = library;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
    public static void method() {
//        静态方法不能访问非静态属性 --》 类的加载机制 先加载类的信息,后对象信息
//        静态信息优先加载 故非静态属性和方法还未加载 不能直接访问
//        非静态方法可以访问静态方法和静态属性,当然 其他非静态的也能访问
//        静态方法中没有this关键字 this是对象,静态方法是类名调用 刚加载时没有对象 虽然也能通过对象访问,但不推荐
//        System.out.println(num);//不能直接访问
        System.out.println("这是一个静态方法");

    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", num=" + num +
                '}';
    }
}

测试类:?

public class TestSchool {
    public static void main(String[] args) {
        School school = new School("莲塘一中", 3000);
        System.out.println(school.getLibrary());
//        school.library //报错 私有属性不能直接访问
        school.method();//不推荐
        School.method();
        School school1 = new School();
    }
}

结果:?

总结:

????????代码加载过程:先是静态,然后是非静态,最后是构造器。

继承?

?????????类和类之间的关系有很多中,继承就是其中一种关系,通过关键字extends实现。

?固定格式

[public] class 子类名 extends 父类名 {
    子类新增内容;
}

继承的特点?

  1. Java只支持单继承,不支持多继承。
  2. Java不支持多继承,但支持多重继承。如:子类 A 继承父类 B ,父类B 继承爷爷类 C

继承的细节和易错:?

  • ?子类只能继承父类所有非私有的成员(含成员方法和成员变量,包括静态方法)
  • Java中的类,如果类定义时没有指定父类,那么这个类会默认继承Object类
  • Java中的每个类都直接或间接继承java.lang.Object(根基类),Object类是Java继承体系中的最顶层父类。
  • 当子类对象被创建时 (默认)会自动调用父类的无参构造器。

案例:?

/**
 * 继承了 Object(Object类没有父类 其他的都有父类,也都可以成为子类)
 * 任何类都继承了java.lang.Object(根基类)
 * 继承可以提高代码的复用性(不重复定义方法 使用父类的方法)
 */
public class Father {//extends Object
    public int a;
    private int b;
    private void test() {
        System.out.println("test");
    }
    public static void method1() {
        System.out.println("这是父类的静态方法");
    }
    public void testA() {
        System.out.println("testA");
    }

}
class Son extends Father{
    //    子类只能继承父类所有非私有方法和属性
    public void method() {
        System.out.println(a);//0
//        System.out.println(b); //私有属性不可继承 故不可使用
    }

    public static void main(String[] args) {
        Son son = new Son();
        son.method();//输出0
//        静态方法也能被继承
        son.method1();//这是父类的静态方法
        System.out.println(son.toString());//继承了object中的toString()方法
    }
}

super关键字?

????????当从父类继承的非private成员,和子类新增的成员重名时,借助super关键字可以区分两个成员 。

? ? ? ? super表示子类继承父类的那部分。

super内存图

super的注意事项?

  • super.属性只能放在第一行(意味着不能和this.属性关键字同时使用)?
  • super代表父类存储空间的标识(可以理解为父类对象引用)
  • super();显式地调用父类的无参构造器;super(参数):调用父类有参构造器

代码展示:?

public class Father {
    public int id;

    public Father() {
        System.out.println("父类构造器");
    }

    public Father(int id) {
        this.id = id;
    }

    public static void method1() {
        System.out.println("这是父类的静态方法");
    }
    public static void main(String[] args) {
//      当子类对象被创建时 (默认)会自动调用父类的无参构造器
        Son son = new Son();
        System.out.println(son);
        Son jack = new Son("jack", "北京");
        System.out.println(jack);
        Son joker = new Son("joker", "北京",1);
        System.out.println(joker);
        son.method1();
//        joker.method();
    }
}
class Son extends Father{
    private String name;
    private String city;

    public Son() {
        super();//显式地调用父类的无参构造器 可以不写,系统默认有
        System.out.println("子类构造器");
    }
//    @Override
    private void method() {
        System.out.println("Son");
    }

    public Son(String name, String city) {
        this.name = name;
        this.city = city;
    }
    public Son(String name, String city,int id) {
        super(id); //super调用父类构造器一定要放在第一行
        this.name = name;
        this.city = city;
//        this.id = id;//或者super.id = id

    }

    @Override
    public String toString() {
        return "Son{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

运行结果:?

文章来源:https://blog.csdn.net/GLimerence/article/details/135665517
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。