一、static关键字

静态(static)可以修饰属性和方法。
称为静态属性(类属性)、静态方法(类方法)。
静态成员是全类所有对象共享的成员。
在全类中只有一份,不因创建多个对象而产生多份。
不必创建对象,可直接通过类名访问。

示例1:

  1. package com.alpaak.part4;
  2. /**
  3. * 静态变量,属于类,和对象无关,
  4. */
  5. public class Demo1_Person {
  6. String name;
  7. int age;
  8. static String city;//静态的,属于类,对象也可以访问,但是所有的对象共享着一份数据;
  9. static final double PI = 3.14;//表示静态的常量,运行的过程数据不能改变,同时属于类,可以用类名直接调用
  10. public void eat(){
  11. System.out.println(this.name+",吃东西啦。。。"); //非静态方法,可以访问非静态属性
  12. System.out.println("城市:"+ Demo1_Person.city); //非静态方法,可以访问静态属性
  13. this.showInfo(); // 非静态方法,可以调用非静态方法。
  14. Demo1_Person.printCity(); //非静态方法,可以调用静态方法。
  15. }
  16. public static void test(){ //属于类的
  17. System.out.println(Demo1_Person.city); //静态方法中,可以访问静态属性。
  18. Demo1_Person.printCity();//静态方法中,可以访问静态方法。
  19. // System.out.println(name); //静态方法中,不能访问非静态的属性
  20. // this.showInfo(); //静态方法中,不能调用非静态的方法。
  21. }
  22. /**
  23. * 静态的方法
  24. */
  25. public static void printCity(){
  26. test();
  27. //System.out.println("name:"+name);
  28. // eat();
  29. System.out.println("城市:"+ Demo1_Person.city);
  30. }
  31. public void showInfo(){
  32. printCity();
  33. eat();
  34. System.out.println("name:"+this.name+",age:"+age+",city:"+city);
  35. }
  36. }

静态属性

形成静态属性,不再属于对象。非静态属性(实例属性)属于对象,随着对象的创建而产生,每个对象的属性值都是独立的。
静态属性是属于类的,只有一份(节省内存)。应该由类来访问,但是对象也可以访问,所有的对象共享着一份数据。
非静态属性由对象访问:对象.属性—>赋值,取值
静态属性由类访问:类名.静态属性—>赋值,取值
静态属性可以和final搭配使用,形成静态常量

静态方法

形成了静态方法。属于类而不再属于对象了,应该由类来访问,但是对象也可以访问。
普通的方法由对象调用。

静态方法中:只能访问属于类,不能访问属于对象。
A:访问静态属性
B:访问静态方法
C:不能直接访问非静态属性
D:不能直接访问非静态方法

非静态方法中:属于类,属于对象都可以访问
A:访问静态属性
B:访问静态方法
C:访问非静态属性
D:访问非静态方法

静态代码块

代码块,就是一块代码。使用static{}包裹起来的。

示例2:

  1. package com.alpaak.part4;
  2. /**
  3. * @Description: 类描述
  4. * @author: alpaak
  5. * @date: 22/01/26 17:06
  6. * @Since 1.0
  7. */
  8. public class Demo2_Static_Block {
  9. String name;
  10. int age;
  11. static{
  12. System.out.println("这是静态代码块。。。。");
  13. }
  14. /*
  15. 构造代码块:需要调用构造函数才会执行
  16. */
  17. {
  18. System.out.println("这是构造代码块");
  19. }
  20. public Demo2_Static_Block(){
  21. System.out.println("这是无参的构造函数");
  22. }
  23. public Demo2_Static_Block(String name,int age){
  24. this.name = name;
  25. this.age = age;
  26. System.out.println("这是有参构造: 姓名:" + name + ",年龄: " +age );
  27. }
  28. public static void main(String[] args) {
  29. System.out.println("\n第一个构造函数生成:");
  30. Demo2_Static_Block demo2_1 = new Demo2_Static_Block();
  31. System.out.println("\n第二个构造函数生成:");
  32. Demo2_Static_Block demo2_2= new Demo2_Static_Block();
  33. System.out.println("\n第三个构造函数生成:");
  34. Demo2_Static_Block demo2_3= new Demo2_Static_Block("小明",32);
  35. }
  36. }

普通代码块:{}包裹起来一段代码。注意作用域。
构造代码块:写在类里,方法外的代码块,就叫构造代码块。当创建对象的时候,随着构造函数的调用而执行。而且优先于构造函数执行。构造函数被多次调用,那么构造代码块也被多次调用。
静态代码块:用static关键字修饰的代码块。在类第一次使用的时候执行,优先于main的执行。只执行一次。例如连接数据库的驱动等
同步代码块:多线程。
优先级别:静态代码块 > 构造代码块 >构造方法

二、继承

概念

生活中我们经常听到一些名词,譬如富二代,官二代,红二代,穷二代,农二代等等,它代表中人与人之间的一种关系。那么程序当中怎么表示这种关系呢?
概念:描述两个类的关系的。在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类(派生类,SubClass),现有类被称作父类(超类,SuperClass),子类会自动拥有父类所有非私有的属性和方法
意义:
A:避免重复的代码。(从子类的角度)
B:扩展类的功能。(从父类的角度)
继承性:子类,父类。存在继承关系。
子类对象,可以直接访问父类的非私有的属性和方法。(避免重复代码)
子类也可以新增自己的属性和方法。(扩展类的功能)
子类可以重新实现父类已有的方法。(扩展类的功能)

语法

父类:A类
子类:B类
语法结构:

class 父类{

}

class 子类 extends 父类{

}

extends关键字:表示两个类是继承关系。

示例3:

package com.alpaak.part4.demo3;

public class Person {
    String name;
    int age;

    public void eat(){
        System.out.println("吃东西。。。。。");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}
package com.alpaak.part4.demo3;

/**
* extends关键字:表示两个类是继承关系。
 *
 */
public class Student extends Person{

    String school;

    //@Override可以不加,但是如果加上,子类的重写的方法一定要和父类的那个方法名相同
    public void eat(){
        System.out.println("学生吃东西。。。。。");
    }

    public void study(){
        System.out.println("学习了。。。。。");
    }

}
package com.alpaak.part4.demo3;

/**
 * 测试继承
 */
public class Test {
    public static void main(String[] args) {
        //父类的创建
        Person p1 = new Person();
        p1.name = "大佬";
        p1.age = 55;
        p1.eat();
        p1.sleep();
        //p1.study();父类无法访问子类新增的方法和属性

        System.out.println("\n=========村刀学院华丽分割线===========\n");

        Student stu = new Student();
        stu.name = "小学生";
        stu.age = 34;
        stu.eat();
        stu.sleep();

        stu.school = "村刀学院";
        System.out.println("学校: "+stu.school);
        stu.study();//子类肯定可以访问新增的方法
    }
}

继承中的构造方法

示例4:

package com.alpaak.part4.demo4;

/**
 * 父类,动物类
 */
public class Animal {
    String name;
    int age;

    public Animal(){
        System.out.println("父类的无参的构造方法。。");
    }

    //有参的构造方法
    public Animal(String name,int age){
        System.out.println("父类的有参的构造方法。。");
        this.name = name;
        this.age = age;
        System.out.println("名称:" + this.name + ",年龄: " + this.age);
    }
}
package com.alpaak.part4.demo4;

public class Cat extends Animal {
    String color;

    public Cat(){

    }

    public Cat(String name,int age,String color){
//        super();//默认调用,隐含调用父类的无参的构造方法
        super(name,age);
        this.color = color;
    }

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

}
package com.alpaak.part4.demo4;

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat("黑猫",12,"黑色");
        cat.catchMouse();
    }
}

super关键字

子类对象的创建过程:
子类的构造方法中,默认先调用父类的无参构造方法。如果没有显示的调用,那么隐含着super()。
super关键字
可以访问父类的属性
可以访问父类的方法
指代父类的构造方法, 如果有多个,靠参数来区分。要在第一行。
this关键字
作为本类的对象,
访问本类的属性。如果在继承中,本类没有这个属性,那么再找父类中。
访问本类的方法
可以指代本类的构造方法:this()。要在第一行。

示例5:

package com.alpaak.part4.demo5;

class A{
    int i=100;
    int j = 200;

    public void test(){
        System.out.println("i---->"+this.i);
        System.out.println("j---->"+this.j);
        System.out.println("------------test1-------------");
    }

    public void fun(){
        System.out.println("父类的fun()方法。。。");
    }

}
package com.alpaak.part4.demo5;

class B extends A{

    int i = 300;

    public void test2(){
        System.out.println("i super------>"+super.i);//访问父类
        System.out.println("i this------>"+this.i);//子类有的,就访问子类

        System.out.println("\nj super------>"+super.j);//访问父类
        System.out.println("j this------>"+this.j);//如果子类没有相应的属性,那么会默认去找父类的属性
        System.out.println("------------test2-----------------");

        this.fun();
    }
}
package com.alpaak.part4.demo5;

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.test2();
    }
}

this和super的对比:
第4章 面向对象(二) - 图1

this,super关键字,不能出现在static方法中。

方法重写[重点]

重写:
关键字:override
概念:继承关系中,子类将父类已有的方法重新实现,叫做方法的重写。

示例6:

package com.alpaak.part4.demo6;

public class Animal {

    public void eat(){
        System.out.println("动物吃东西。。。。");
    }
}
package com.alpaak.part4.demo6;

public class Fish extends Animal {

    @Override
    public void eat() {
        System.out.println("鱼游海底。。。。吃东西。。。");
    }

}
package com.alpaak.part4.demo6;

/**
 * 测试重写
 */
public class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();//父类对象,访问父类方法

        Fish fish = new Fish();
        fish.eat();//子类对象,访问子类重写后的方法。。。
    }
}

重写与重载的对比

第4章 面向对象(二) - 图2

三、访问修饰符

访问权限:对类,方法,变量,常量等访问位置的限定。通过访问权限修饰符来实现。
在Java中,可以在类、类的属性以及类的方法前面加上一个修饰符(modifier),来对类进行一些访问上的控制。
private:私有的,限制在本类中才能访问。
default:什么都不写,就是default。同类,同包。
protected:受保护的,同类,同包,不同包(限于子类访问)
public:公共的,同类,同包,不同包。
对类的修饰:只能是default和public。protected不能修饰一个类。

访问控制
第4章 面向对象(二) - 图3
最终结论:
private<default<protected<public

示例7:

基本类

package com.alpaak.part4.demo7.test;

public class Demo7_Access {

    private int age;//private 只能在本类中访问

    int i;//default:什么都不写,就是default。同类,同包。

    protected int j;//protected:受保护的,同类,同包,不同包(限于子类访问)

    public void print(){//public:公共的,同类,同包,不同包。
        System.out.println("age:"+age);
    }

}

同一个包,不同的类

package com.alpaak.part4.demo7.test;

/**
 * 同一个包,不同的类
 */
public class Test1 {

    public static void main(String[] args) {
            Demo7_Access d1 = new Demo7_Access();
            //d1.age //无法访问私有属性

            d1.i = 100;//default修饰的可以在同一个包中访问
            System.out.println("i的值:"+d1.i);

            d1.j = 200;//protected修饰的,可以在同一个包中访问
            System.out.println("j的值:"+d1.j);

            d1.print();//同一个包中,可以访问
    }
}

同一个包中,子类

package com.alpaak.part4.demo7.test;

/**
 * 同一个包中,子类
 */
public class Test2_Sub extends Demo7_Access {

    public void test(){
        //System.out.println(""+this.age);无法访问私有属性
        System.out.println(""+this.j);//子类可以访问
    }
}

不同的包,子类

package com.alpaak.part4.demo7.test1;


import com.alpaak.part4.demo7.test.Demo7_Access;

/**
 * 不同的包,子类
 */
public class Test3_Sub extends Demo7_Access {
    public void subTest(){
        System.out.println(""+this.j);//protected修饰的属性,在不同的包中,子类也可以访问
    }
}


四、final关键字

词意:终结的,最终的,最后的。
final可修饰的内容:
类(最终类)
方法(最终方法)
变量(最终变量)

final修饰类:此类不能被继承。String、Math、System均为final修饰的类,不能被继承。 final修饰方法:此方法不能被覆盖。意为最终方法,不支持子类以覆盖的形式修改。

final修饰变量:此变量值不能被改变(常量)。所有final修饰的变量只能赋值一次,值不允许改变。

final修饰基本类型:值不可变
final修饰引用类型:地址不可变
静态常量不再提供默认值,必须手动赋予初始值。
示例:

package com.alpaak.part4.demo8;

//public final class Animal {//final修饰的类,是不能被继承的
public class Demo8_final {
    // 常量 不可更改
    public static final double PI = 3.14;

//    public final void eat(){//修饰的方法,不能被重写
//        System.out.println("动物吃东西。。。。。。");
//    }

    public  void eat(){
        System.out.println("动物吃东西。。。。。。");
    }
}

五 项目源码地址

https://gitee.com/alpaak/hello-java.git

使用gitbash命令下载:
git clone https://gitee.com/alpaak/hello-java.git