Java语言基础-面向对象编程三步走之关上冰箱门

面向对象编程高阶

关键字:static

Static关键字可以用来修饰属性、方法、代码块、内部类。

使用Static修饰的属性叫做静态变量。

我们在实例化类时,会开辟一块内存空间,空间内存放着各自的属性与方法。假如类中有一个属性不管声明多少次,值都是一个固定的值,那么我们可以把他设置成一个静态变量。这样的话这个属性就不是所有对象都有一个,而是所有对象共享一个,可以极大的降低内存使用。

public class StaticTest {
    public static void main(String[] args) {
        Student s1 = new Student("小明",20);
        s1._class = "一班";

        Student s2 = new Student("小王",22);
        s2._class = "二班";

        System.out.println(s1._class);
        System.out.println(s2._class);
    }
}

class Student{
    String name;
    int age;
    static String _class;
    // 使用static声明静态变量

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

----------
    二班
    二班

静态变量随着类的加载而创建,而示例变量要随着对象的创建而创建,也就是说静态变量在运行到类的时候就开始创建了,后者要等new的时候才创建。

也就是说我们可以通过类名直接去调用静态变量

Student._class = "二班"

内存图:
在这里插入图片描述
使用Static修饰的方法叫做静态方法。

public class StaticTest {
    public static void main(String[] args) {
        Student s1 = new Student("小明",20);
        s1._class = "一班";

        Student s2 = new Student("小王",22);
        s2._class = "二班";
    }
}

class Student{
    String name;
    int age;
    static String _class;
    // 使用static声明静态变量

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

    public static void show(){
        System.out.println(_class);
        // 静态方法中不可以调用属性,只能调用静态变量或者自己的局部变量。
        // 转换一下思维,既然main也是一个static方法,是不是可以在主类中声明静态变量作为全局变量呢?
    }

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

关于static的经验之谈

  • 如何确定一个变量是否要声明为static

    属性是可以被多个对象所共享的,不会随着对象的不同而不同。

    一般常量都声明static。

  • 如何确定一个方法是否要声明为static

    操作静态属性的方法,通常设置为static

    工具类的方法,例如Math,Arrays等等

理解main方法的语法

  1. main()方法作为程序的入口
  2. main()方法也是一个普通的静态方法
  3. main()也可以作为与控制台交互的方式
    在这里插入图片描述

代码块

代码块是用来初始化类,对象的

代码块只能使用static关键字修饰

定义一个代码块:

public class BlockTest {
    public static void main(String[] args) {
        String desc = Person.desc;  // 此时静态代码块执行
        System.out.println(desc);

        Person p1 = new Person("张三", 15);	// 此时非静态代码块执行
        p1.eat();
    }
}

class Person{
    // 属性
	String name;
	int age;
    static String desc = "我是一个学生";

    // 构造器
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
    
    /**
     * 代码块:
     *      内部可以有输出语句
     *      随着对象的创建而执行
     *      每创建一个对象,就执行一次非静态代码块
     *      可以在创建对象时,对对象的属性等进行初始化
     *      如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
     *      非静态代码块内可以调用静态的属性、静态的方法,或者非静态的属性与方法
     */
	{
        System.out.println("hello block");
	}
    
    /**
     * 静态代码块:
     *      内部可以有输出语句
     *      随着类的加载而执行,且只执行一次
     *      初始化类的信息
     *      如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
     *      静态代码块的执行要优先于非静态代码块
     *      静态代码块只能调用静态的属性、静态的方法,不能调用非静态的结构    
     */
    static{
        System.out.println("hello static block");
    }


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

	
}

如果有父子继承关系:

先执行所有的静态代码块。

再由父及子依次执行非静态代码块与构造器。

由父及子,静态先行。

关键字:final

final可以用来修饰类,方法,变量。

final声明的类,不可以被继承。

比如String类是用final声明的,所以我们不能定义一个类来继承他。
在这里插入图片描述

报错惹
在这里插入图片描述

声明final的方法也不可以被重写

在这里插入图片描述

被final修饰的变量就变成一个常量了。然后我们可以显式赋值或者在代码块中赋值。

抽象类与抽象方法

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征,有时将一个父类设计的非常抽象,以至于他没有具体的实例,这样的类叫做抽象类。

image-20200526160350529

public class AbstractTest {
    public static void main(String[] args) {
        Students s1 = new Students("张三", 18);
        s1.eat();
    }
}

/**
 * abstract 修饰类,抽象类
 *      此类不能实例化
 *      抽象类中一定有构造器,便于子类实例化时调用
 *      开发中,都会提供抽象类的子类,让子类对象实例化
 *      
 */
abstract class Persons{
    // 属性
	String name;
	int age;
    static String desc = "我是一个学生";

    // 构造器
	public Persons(String name,int age){
		this.name = name;
		this.age = age;
	}
    
    // 方法
	public void eat(){
		System.out.println("吃饭");
    }

    /**
     * 抽象方法
     * 抽象方法只有方法的声明,没有方法体
     * 只能在抽象类中定义抽象方法
     */
    public abstract void walk();
	
}

class Students extends Persons{
    public Students(String name,int age){
        super(name, age);
    }
    
    /**
     * 子类必须重写父类所有的抽象方法后才可以实例化
     * 如果子类没有重写父类所有的抽象方法,则子类也必须是一个抽象方法
     */
    public void walk(){

    }
}

注意点:

  1. abstract不能修饰属性,构造器等结构
  2. abstract不能用来修饰私有方法

抽象类的匿名子类

public class PersonTest {
    public static void main(String[] args) {
        method(new Student("小明",20));  // 匿名对象

        Worker worker = new Worker("小王", 20);
        method1(worker);                // 非匿名类非匿名对象


        method1(new Worker("大王", 35));// 非匿名类匿名对象

        Person p = new Person(){
            @Override
            public void eat(){
                
            }
        };

        method1(p);                     
    
        method1(new Person(){
            @Override
            public void eat(){
                
            }
        });                         // 匿名类匿名对象
        

    }

    public static void method(Student s){

    }

    public static void method1(Person p){
        p.eat();
    }
}

class Worker extends Person{
    public Worker(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat(){
        
    }
}

最后:

面向对象的思想概述

  • 程序员从面向过程的执行者转换为面向对象的指挥者
  • 面向对象分析方法分析问题的思路和步骤:
    • 根据问题需要,选择问题所针对的现实世界的实体
    • 从实体中寻找解决问题相关的属性和功能,这些属性和功能就形成了概念世界中的类
    • 把抽象的实体用计算机语言进行描述,形成计算机世界中类的定义,借助某种程序语言,把类构造成计算机能够识别和处理的数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

寒 暄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值