6.从零开始学习Java-三个修饰符

三个修饰符

abstract:(自然、强制实现多态)为了更自然的使用多态。抽象方法只声明不实现。不能创建对象new anmial,父类唯独不能独立使用构造方法创造对象。一般用于抽象类作为父类,子类将抽象方法覆盖。

static:(类)静态方法可以被继承,不能被覆盖,不能多态。不必创建对象,可直接通过类名访问,本类直接方法名,其他类通过类名.调用。

final:(最终)方法不能被继承,不能被覆盖,变量不能被修改,初始化需要赋值。

一、abstract

//更像是为多态的使用制定的一种规范。

//抽象类,更自然的使用多态。//强制使用Animal a = new Dog();

//抽象方法,只声明,不实现。

//抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。

1.1 必要性:

现实中存在的都是"动物"具体的子类对象,并不存在"动物"对象,像Animal不应该被独立创建成对象。

不该被实现的方法:

方法声明必要,方法实现多余。

1.2 抽象类:

概念和应用:

Animal是抽象的,无法实例化。

被abstract修饰的类,称为抽象类。

抽象类意为不够完整的类、不够具体的类,抽象类对象无法独立存在,即不能new对象。

抽象类的作用:

1.可被子类继承,提供共性属性和方法。

2.可声明为引用,更自然的使用多态。//强制使用Animal a = new Dog();

语法:

abstract class Animal {
    
}

1.3 抽象方法:

被abstract修改的方法,称为抽象方法,
只有方法声明,没有方法实现({}的部分)。
意为不完整的方法,必须包含在抽象类中

产生继承关系后,子类必须重写父类中所有的抽象方法,否则子类还是抽象类。

语法:

public abstract void eat();//抽象方法,只有声明,没有实现,不够完整。

1.4 经验:

抽象父类,可作为子类的组成部分,依附于子类对象存在,由父类共性+子类独有组成完整的子类对象。

抽象方法:(abstract只有方法的声明,实现多余,因为它只是用来提供有这个方法)

被abstract修改的方法,称为抽象方法,只有方法声明,没有方法实现({}的部分)。意为不完整的方法,必须包含在抽象类中。

1.5 总结:

  • abstract修饰类:不能new对象,但可以声明引用。
  • abstract修饰方法:只有方法声明,没有方法实现。(需包含在抽象类中)
  • 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。
  • 子类继承抽象类后,必须重写父类中所有的抽象方法,否则子类还是抽象类

1.6 代码实现:

//父类
abstract class Animal {//逻辑:不够完整、不够具体
    String breed;
    int age;
    String sex;
    public Animal(){
        System.out.println("父类唯独不能独立使用构造方法创造对象");
    }
//    public void eat(){
//        System.out.println("动物在吃。。");
//    }
    public abstract void eat();//抽象方法:只有声明,没有实现(不够完整)
    public void sleep(){}
}
//子类
public class Dog extends Animal {
    String furColor;
    public Dog(){
        super();
        System.out.println("从子类调");
    }
    public void eat(){
        System.out.println("狗吃");
    }
    public void run(){

    }
}
//测试
public class TestAbstract {
    public static void main(String[] args){
//错误        new Animal();//Error 不能独立存在
//正确      new Dog();//Correct
        Animal a = new Dog();
        System.out.println(a.breed);
        a.eat();
    }
}

二、static(类属性、方法)

//无需创建对象,通过类名访问。

//静态方法访问静态成员,不能访问非静态成员。

//可以继承,不能覆盖,没有多态。

2.1 实例属性:

实例属性是每个对象各种持有的独立空间(多份),对象单方面修改,不会影响其他对象。

//每个栈中的地址对应一个堆中的地址。

public class TestStaticField{
    public static void main(String[] args){
        MyClass mc1 = new MyClass();
        mc1.a = 100;
        MyClass mc2 = new MyClass();
        mc2.a = 200;
        System.out.println(mc1.b+"\t"+mc2.b);
    }
}
class MyClass{
    int a;
}
输出结果:
    100	200

2.2 静态属性(类属性):

静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。

public class TestStaticField{
    public static void main(String[] args){
        MyClass mc1 = new MyClass();
        mc1.b = 100;
        MyClass mc2 = new MyClass();
        mc2.b = 200;
        System.out.println(mc1.b+"\t"+mc2.b);
        System.out.println(Myclass.b);//可以通过类名直接访问。
    }
}
class MyClass{
    static int b;//静态属性
}
输出结果:
    200	200
    200

2.3 什么是静态:(一般全类计数用的变量,只有一份。)

  • 静态(static)可以修饰属性和方法。

  • 称为静态属性(类属性)、静态方法(类方法)。

  • 静态成员是全类所有对象共享的成员。

  • 在全类中只有一份,不因创建多个对象而产生多份。

  • 不必创建对象,可直接通过类名访问。

2.4 静态方法:

public class TestStaticMethod{
    public static void main(String[] args){
        MyClass.method1();//可在其他类中,通过“类名.静态方法名”访问。
    }
class MyClass{
    public static void method1(){
        System.out.println("MyClass static method1()");
        method2();//可在本类中,通过“静态方法名”访问。
    }
    public static void method2(){//由static修饰的静态方法。
        System.out.println("MyClass static method2()");
    }
}
}

//静态方法可在其他类中通过“类名.静态方法名”访问。不用new。

//实例方法则是伴随的对象的产生才能调用。

已知静态方法:

Arrays.copyOf();

Arrays.sort();

Math.random();

Math.sqrt();

均使用类名直接调用

2.5 静态的特点:

  • 静态方法允许直接访问静态成员。
  • 静态方法不能直接访问非静态成员。
  • 静态方法中不允许使用this或是super关键字。
  • 静态方法可以继承,不能覆盖,没有多态。
public class A {
    static int field;
    public static void staticMethod(){//静态方法只能调用静态属性,不能调用非静态方法
        System.out.println(field);
    }
}
public class TestAccessNotStatic {
    public static void main(String[] args){
      A.staticMethod();//通过类名直接调用。
        //静态方法是可以通过类名调用的(在调用该方法时,可能从未创建过对象)
    }
}
//可以使用继承,无需创建对象,直接通过类名调用,无需创建对象。
//子类
public class B extends A{
}
//测试类:
public class TestAccessNotStatic {
    public static void main(String[] args){
      A.staticMethod();//通过类名直接调用。
        //静态方法是可以通过类名调用的(在调用该方法时,可能从未创建过对象)
        B.staticMethod();//继承通过类名直接调用,无需创建对象。
    }
}

2.6 局部代码块:

局部代码块,会缩小变量的使 用范围,提前释放局部变量, 节省内存。

public class TestLocalBlock{
    public static void main(){
        int num=100;
        {
            int age = 20;
            System.out.println(age);
            System.out.println(num);
        }
        int num2 = 500;
        System.out.println(num);
        System.out.println(num2);
    }
}
运行结果:
20
100
100
500

2.7 动态代码块:

//没太大用,构造方法可以替代。

//写在类下面的代码块是动态代码块。执行对象便执行动态代码块。先执行动态代码块再执行构造方法。

创建对象时,触发动态代码块的执行。

执行地位:初始化属性之后、构造方法代码之前。

作用:可为实例属性赋值,或必要的初始行为

public class TestDynamicBlock{
    public static void main(String[] args){
        new MyClass();
    }
}
class MyClass{
    String field = "实例属性";
        public MyClass(){
        System.out.println("构造方法");
    }
    {
        System.out.println(field);
        System.out.println("动态代码块");
    }

}
结果:
实例属性
动态代码块
构造方法

2.8 类加载:

1.JVM首次使用某个类时,需通过CLASSPATH查找该类的.class文件。

2.将.class文件中对类的描述信息加载到内存中,进行保存。

javap命令

java -verbose:class xxx//观察加载的类

javap -verbose xxx > xxx.bytecode//反编译文件

如:包名、类名、父类、属性、方法、构造方法…

加载时机:

  • 创建对象。
  • 创建子类对象。
  • 访问静态属性。
  • 调用静态方法。
  • 主动加载:Class.forName(“全限定名”);//主动加载一个类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.9 静态代码块:

//静态代码块是由类加载触发的。类加载便执行静态代码块,静态属性初始化之后,只会执行一次。

类加载时,触发静态代码块的执行(仅一次)。

执行地位:静态属性初始化之后。

作用:可为静态属性赋值,或必要的初始行为。

public class TestStaticBlock{
    public static void main(String[] args){
        MyClass.method();
    }
}
class MyClass{
    static String sField = "静态属性";
    static{
        System.out.println(sField);
        System.out.println("静态代码块");
    }
    public static void method(){
        /*无代码
        *只为触发静态属性的初始化
        *和静态代码块的执行
        */
    }
}
运行结果:
    静态属性
    静态代码块

执行顺序总结:

public class Super {
    static String staticField = "父类静态属性";
    static {
        System.out.println(staticField);
        System.out.println("父类静态代码块");
    }
    String instanceField = "父类实例属性";

    {
        System.out.println(instanceField);
        System.out.println("父类实例代码块");
    }
    public Super(){
        System.out.println("父类构造方法");
    }
}
public class TestLoadSort {
    public static void main(String[] args){
      new Super();
    }
}
执行结果:
父类静态属性
父类静态代码块
父类实例属性
父类实例代码块
父类构造方法
//父类
public class Super {
    static String staticField = "父类静态属性";
    static {
        System.out.println(staticField);
        System.out.println("父类静态代码块");
    }
    String instanceField = "父类实例属性";

    {
        System.out.println(instanceField);
        System.out.println("父类实例代码块");
    }
    public Super(){
        System.out.println("父类构造方法");
    }
}
//子类
public class Sub extends Super {

        static String staticField1 = "子类静态属性";
        static {
            System.out.println(staticField1);
            System.out.println("子类静态代码块");
        }
        String instanceField1 = "子类实例属性";

        {
            System.out.println(instanceField1);
            System.out.println("子类实例代码块");
        }
        public Sub(){
            System.out.println("子类构造方法");
        }
}
//测试类
public class TestLoadSort {
    public static void main(String[] args){
      new Sub();
    }
}
执行结果:
父类静态属性
父类静态代码块
子类静态属性
子类静态代码块
父类实例属性
父类实例代码块
父类构造方法
子类实例属性
子类实例代码块
子类构造方法
//只修改测试类
public class TestLoadSort {
    public static void main(String[] args){
        new Sub();
        new Sub();
    }
}
执行结果:
父类静态属性
父类静态代码块
子类静态属性
子类静态代码块
父类实例属性
父类实例代码块
父类构造方法
子类实例属性
子类实例代码块
子类构造方法
父类实例属性
父类实例代码块
父类构造方法
子类实例属性
子类实例代码块
子类构造方法

总结:

• static修饰的成员为静态成员,无需创建对象,可直接通过类名访问。

• 静态方法不能直接访问非静态成员。

• 静态方法中不能使用this或super。

• 静态方法可以继承、不能重写、没有多态。

• 静态代码块在类加载时被执行,且只执行一次

三、final(最终类、属性、方法)

3.1 final可修饰的内容:

类(最终类)

方法(最终方法)

变量(最终变量)

3.2 final类:

1.final修饰类:此类不能被继承。

String、Math、System均为final修饰的类,不能被继承。

2.final修饰类:此方法不能被覆盖。

意为最终方法,不支持子类以覆盖的形式修改。

3.3 final变量

变量:字面常量、符号常量

final修饰变量:此变量值不能被改变(常量)

所有的final修饰的变量只能赋值一次,值不允许改变。

//错误案例
public class TestFinal{
    public static void main(String[] args){
        final int num = 10;
        //num = 20;//错误用法,无法为最终变量num分配值
    }
}

3.3.1 实例变量:

实例常量不再提供默认值,必须手动赋予初始值。//其值不能改变

赋值时机:显示初始化、动态代码块、构造方法。

注意:如果在构造方法中为实例常量赋值,必须保证所有的构造方法都能对其正常赋值。

//错误案例
public class TestFinal{
    public static void main(String[] args){
        new Student();
    }
}
class Student{
    //final String name;// = "Tom"//错误:可能尚未初始化变量name
    {
        //正确
        //方法块外final String name;
        name = "tom";
        //或者
        final String name = "tom";
    }
    public Student(){
        //正确
        final String name = "tom";
    }
}

3.3.2 静态常量:

静态常量不再提供默认值,必须手动赋予初始值。
赋值时机:显示初始化、静态代码块。

public class TestFinal{
    public static void main(String[] args){
        System.out.println(Student.SCHOOL_NAME);
    }
}
class Student{
    //static final String SCHOOL_NAME;//="xx小学"//错误:可能尚未初始化变量SCHOOL_NAME
    static{
        //正确
        //SCHOOL_NAME = "北京市第一中学";
        //静态常量不再提供默认值,必须手动赋予初始值。
        //赋值时机显示初始化、静态代码块。
    }
}

3.3.3 对象常量:

public class TestFinal{
    public static void main(String[] args){
        final int num = 100;
        //错误
        //num += 20;//final修饰基本类型:值不可变
        final int[] nums = new int[]{11,22,33};
        //正确
        //nums[0] = 88;
        //错误
        //nums = new int[5];//final修饰引用类型:地址不可变
        final Student s = new Student();
        //错误
        //s = new Student();//
    }
}
class Student{
   	String name;
}

3.4 总结:

• final修饰类:此类不能被继承。 (最终类)

• final修饰方法:此方法不能被覆盖。 (最终方法)

• final修饰变量:此变量值不能被改变。(最终变量)(无初始值、只允许赋值一次)

  • 局部常量:显示初始化。
  • 实例常量:显示初始化、动态代码块、构造方法。
  • 静态常量:显示初始化、静态代码块。
  • 基本类型常量:值不可变。

• 引用类型常量:地址不可变。

• abstract不能和final同时使用。

• abstract不能和static同时使用

2.final类不能被子类重写,但是可以被子类继承。

final变量:

常量:字面常量、符号常量//fianl修饰局部变量变成常量。

final修饰变量:此变量值不能被更改。

//final修饰实例变量(常量),赋值方式:1.声明时赋值;2.构造方法中赋值。

final修饰类变量(常量)赋值方式:1.声明时赋值 2.在静态代码块赋值

总结:

final:此类不能被继承

四、方法调用和方法调用指令

	//Java中的方法调用,分为两种
	
	//1.静态分派(静态方法中,允许参数列表不同的重名方法,指静态方法之间的重载)
	
	//2.动态分派(在具有继承关系的情况下,调用实例方法时,自低向上查找可用的方法版本,指实例方法的覆盖)
	//java虚拟机:
	//方法调用指令5个
	//invokespacial 调用私有方法、构造方法
	//invokeinterface 调用接口方法
	//invokestatic 调用静态方法
	//invokevirtual 调用虚方法(父类定义的,日后被子类覆盖的方法)
	//invokedynamic 调用动态链接方法

五、idea快捷键:

alt+enter快速生成代码

alt+insert快速生成构造方法

六、idea找到.class文件的位置

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值