三个修饰符

三个修饰符

  • 学习目标
    认识每种修饰符的可以修饰组件。
    了解每种修饰符修饰组件时的特点。
    概念较多,注意记录。
    
    使用修饰符可以让程序设计的更加合理,通常起到优化的作用。

1 abstract

  • 概念:抽象。
  • 可以修饰的组件:类、方法。
1.1 abstract修饰类
  • 概念:abstract 修饰的类称为抽象类
  • 抽点类特点:只能声明引用不能创建对象。
    演示的代码如下:
package com.txw.test;
public class TestAbstractClass{
	public static void main(String[]args){		
		MyClass mc;		// 声明引用
		// mc = new MyClass();		// 创建对象
		// mc = new Sub();
		// mc = new MyClass();
		mc = new Sub();
		mc.m1();
	}
}
// 抽象类
abstract class MyClass{
	int a;   // 属性
	public void method(){}		// 方法
	public MyClass(){}			// 构造方法
	public abstract void m1(); // 抽象方法
}
// 抽象方法也可以被继承
class Sub extends MyClass{
	// 子类覆盖父类的抽象方法,添加{ }
	public void m1(){
		System.out.println("m1()");
	}
}
1.2 abstract修饰方法
  • 概念:abstract 修饰的方法称为抽象方法

  • 抽象方法的语法:

    访问权限修饰符 abstract 返回值类型 方法名(参数表);
    
  • 抽象方法的特点:

    1. 抽象方法没有{}(实现/方法体)。
      比如:
      public abstract void method();
      
    2. 抽象方法只能存在抽象类中。
      abstract class MyClass{
      	public abstract void m1();		// 抽象方法
      }
      
    3. 抽象方法可以被继承,子类不覆盖抽象方法,子类必须为抽象类。
      abstract class Super{
          // 抽象方法
          public abstract void method();
      }
      // 子类没有覆盖抽象方法,子类必须为抽象类
      abstract class Sub extends Super{
          
      }
      
    4. 子类不想称为抽象类,必须覆盖父类中的所有抽象方法并添加{}(实现)。
      abstract class Super{
          // 抽象方法
          public abstract void method();
      }
      // 子类没有覆盖抽象方法,子类必须为抽象类
      class Sub extends Super{
          // 覆盖父类中的抽象方法,添加{}
          public void method(){ 
          }
      }
      
      子类覆盖父类的抽象的方法,这种特殊的语法称为实现 抽象方法即为办成品方法,父类提供声明(我要做什么),子类提供方法实现(我要怎么做)。
  • 总结:

    1. abstract可以修饰类、方法,被修饰的类称为抽象类,方法称为抽象方法。
    2. 抽象类:只能声明引用,不能创建对象。
    2. 抽象方法:只有方法声明没有方法实现,必须存在于抽象类中,子类继承父类如果父类中有抽象方法则子类也会称为抽象类
               子类不想称为抽象类,必须覆盖父类中的抽象方法并添加实现,这种特殊的覆盖语法称为实现。
    

2 final

  • 概念:最终的。
  • 可以修饰的组件:类、方法、成员变量(属性)、局部变量 。
2.1 final修饰局部变量
  • final修饰的局部变量称为常量。

  • 特点:值不可变,基本数据类型值为数据,引用数据类型值为地址。

    final int a = 10;		// 定义变量并赋值
    a=10;		// 改变变量的值,Error 常量无法改变值
    System.out.println( a );
    
2.2 final修饰成员变量
  • final修饰的成员变量称为成员常量(常量)。

  • 特点:值不可变,且没有默认值,必须手动赋值。
    演示:使用初始化方式直接赋值。

    class MyClass{
    	// 常量属性
    	final int a = 10;
    }
    

    演示:使用动态初始化代码块赋值

    class MyClass{
    	
    	// 常量属性
    	final int a;
    	// 动态初始化代码块,初始化属性时自动执行
    	// 作用为属性赋值
    	// 与构造方法的作用一样
    	{
    		// 使用初始化代码块初始化属性
    		a = 10;
    	}
    }
    

演示:使用构造方法为属性赋值,务必保证每个构造方法中都有赋值语句。

class MyClass{
	// 常量属性
	final int a;
	// 使用构造方法为属性赋值
	public MyClass(){
		a = 10;
	}
	public MyClass(int a){
		this.a  = a;
	}
}
2.3 final修饰方法
  • final修饰的方法称为最终方法。
  • 特点:不能被子类覆盖。
    class Super{
    	public final void method(){}
    }
    class Sub extends Super{
    	// 覆盖错误
    	public void method(){}
    }
    
2.4 final修饰类
  • final修饰的类称为最终类。
  • 特点:不能被继承。
    final class Super{
    	public  void method(){}
    }
    class Sub extends Super{        // Error 不能继承final类
    	// 覆盖
    	public void method(){}
    }
    
  • 总结:
    final表示最终的,可以修饰类、方法、成员变量、局部变量。
    1. 修饰类:称为最终类,不能被继承。
    2. 修饰方法:称为最终方法,不能被覆盖。
    3. 修饰属性:常量属性(成员常量),必须手动赋值,可以通过初始化赋值、动态初始化代码块赋值、构造方法赋值,值能赋值一次,值不可变。
    4. 修饰局部变量:常量(局部常量),只能赋值一次,值不可变,基本数据类型值为数据,引用数据类型值为地址。
    ``
    
package com.txw.test;
public class TestFinal{
	public static void main(String[]args){
		// final int a = 10;	// 定义变量并赋值
		// a=10;	// 改变变量的值
		// System.out.println( a );
		// final int[] as = new int[3];
		// System.out.println( as );
		// as[0] = 10;
		// as = new int[5];
		// System.out.println(as[0]);
		MyClass mc = new MyClass();
		System.out.println( mc.a );
	}
	
}
// 分配空间 为属性分配默认值
// 初始化属性 为属性赋予初值,执行动态初始化代码块
// 调用构造方法
class MyClass{
	// 常量属性
	final int a;
	// 使用构造方法为属性赋值
	public MyClass(){
		a = 10;
	}
	public MyClass(int a){
		this.a  = a;
	}
}
final class Super{
	public  void method(){}
}
class Sub extends Super{
	// 覆盖
	public void method(){}
}

3 static

  • 概念:static表示静态的,与对象无关的。
  • 可以修饰的组件:import、类、属性、方法、动态初始化代码块。
3.1 static修饰属性
  • static修饰的属性称为静态属性

  • 特点:与对象无关,可以直接使用类名访问。

  • 语法如下:

    类名.静态属性名
    

    演示的代码如下:

    class MyClass{
    	int a;
    	static int b;	// 静态属性
    }
    MyClass.b  = 10;		// 使用类名直接访问静态属性
    

    注意:静态属性也可以通过对象的引用访问但不推荐,静态属性存放在共享空间中与对象不在一块内存空间。

3.2 static修饰方法
  • static修饰的方法为静态方法
  • 特点:与对象无关,可以使用类名直接访问。
  • 语法如下:
    访问权限修饰符 static 返回值类型 方法名(参数表){
        
    }
    
    演示的代码如下:
    class MyClass{
    	int a;
    	static int b;		// 静态属性
    	// 一般方法
    	public void m1(){
    		System.out.println("m1() in MyClass");
    	}
    	// 静态方法
    	public static void m2(){
    		System.out.println("static m2() in MyClass");
    	}
    }
    
    MyClass.m2(); 						// 调用静态方法
    
    注意:
    1. 静态方法与对象无关,所以无需创建对象直接使用,不依赖对象所以无法使用this(当前对象)与super(父类对象)关键字。
    2. 静态方法与对象无关,所以不能使用非静态成员(成员变量,成员方法)。
    3. 静态方法可以被继承,只能被静态方法覆盖,使用子类类名直接访问继承到的静态方法。
    4. 静态方法与对象无关,所以不能使用多态。
    
    静态方法通常用于工具方法,因为调用便捷。
3.3 static修饰动态初始化代码块
  • static修饰的动态初始化代码块称为静态初始化代码块
  • 特点:在第一次使用一个类时执行一次。
  • 语法如下:
    // 在类以内,方法以外的位置
    static{
        
    }
    
    执行时机高于构造方法,第一次创建对象时先执行静态初始化代码块。
    使用触发条件:
    1. 第一次创建对象时。
    2. 第一次使用静态成员时(静态属性,静态方法)。
    3. 第一次创建子类对象时,第一次使用子类静态成员时。
    
    只声明引用,不算使用,不可触发静态初始化代码块。
    注意:在静态初始化代码块中,不能使用非静态成员(成员变量,成员方法)。
  • 创建对象的过程:
    1. 分配空间
    2. 执行父类静态初始化代码块(第一次创建)。
    3. 执行子类静态初始化代码块(第一次创建)。
    4. 初始化父类属性、
    5. 调用父类构造方法。
    6. 初始化子类属性。
    7. 调用子类构造方法。
    
    演示的代码如下:
package classes;
public class TestStatic{
	public static void main(String[]args){
		// 访问a属性
		// MyClass mc = new MyClass();
		// mc.a = 100;
		// MyClass.b = 10;
		// MyClass mc1 = new MyClass();
		// mc1.a = 300;
		// MyClass.b  = 20;
		// 访问b静态属性
		// System.out.println( MyClass.b );
		// System.out.println( MyClass.b );
		// MyClass mc = new MyClass();
		// mc.m1();		// 调用方法
		// MyClass.m2();
		// Sub.m2();
		MyClass mc = null;
		// mc.m1();
		// mc.m2(); 
	}
}
class MyClass{
	int a;
	static int b;			// 静态属性
	public void m1(){
		System.out.println("m1() in MyClass");
	}
	// 静态方法
	public static void m2(){
		// System.out.println( a );
		// m1();
		// System.out.println( b );
		System.out.println("static m2() in MyClass");
	}
}
class Sub extends MyClass{
	public void m1(){
		System.out.println("m1() in Sub");
	}
	
	public static void m2(){
		System.out.println("m2() in Sub");
	}	
}
4 import static 静态引入
  • 引入外部的静态资源,使用时可以省略类名.。
    演示的代码如下:
package com.txw.test;
import static java.util.Arrays.sort;
import static java.lang.System.out;
import java.util.Arrays;
public class TestStatic2{
	public static void main(String[]args){
		// MyClass mc;
		// new MyClass();
		// new MyClass();
		// MyClass.m1();
		// MyClass.m1();
		// new Sub();
		int[] a = {6,4,2,1,2,3,4,2};
		// 排序
		sort( a );
		System.out.println( Arrays.toString( a ) );
	}
}
class Super{
	// 静态初始化代码块
	static{
		System.out.println("Super static{ }");
	}
	
	public Super(){
		System.out.println("Super()");
	}
}
class Sub extends Super{
	static{
		System.out.println("Sub static{ }");
	}
	public Sub(){
		System.out.println("Sub () ");
	}
}

5 习题

  1. 关于三个修饰符描述不正确的是(AD)。
    A. static 可以修饰所有类型的变量。
    B. static 可以修饰方法 C. final 可以修饰类。
    D. abstract 可以修饰类、方法、属性。
    原因:A错误static修饰不了局部变量 D错误abstract只能修饰类和方法。
  2. 下面关于 static 描述不正确的是© 。
    A. static 修饰的属性称为静态变量,被所有的对象共享。
    B. static 修饰的方法,可以直接用 类名.方法名(参数)调用。
    C. static 修饰的方法中可以直接访问本类的其他方法 。
    D. 父类中定义了 static 修饰的方法,子类中不能再定义同名的 static 方法。
    原因:C错误静态方法中只能直接访问静态成员
  3. 关于 final 描述错误的是(AB)。
    A. final 修饰的类是作用范围内常量,只允许一次赋值。
    B. final 修饰的方法不能被继承 。
    C. final 修饰的方法不允许被覆盖。
    D. final 修饰的类没有子类。
  4. 关于 abstract,以下选项正确的是:A,B,C,D
    A. abstract 类中可以没有 abstract 方法 。
    B. abstract 类的子类也可以是 abstract 类。
    C. abstract 类不能创建对象,但可以声明引用。
    D. abstract 方法不能有方法体 。
  5. 仔细阅读以下程序,写出程序输出的结果。
    在这里插入图片描述
    答: 300 200 300 400 静态属性是所有对象共享,一方修改影响另一方。实例属性随着创建对象的个数每个对象都拥有一份。
  6. 仔细阅读以下程序,选出哪些代码会导致程序出错() 。在这里插入图片描述
    A. // 1
    B. // 2
    C. // 3
    D. // 4
    E. // 5
    F. // 6
    G. // 7
    H. // 8
    原因:静态方法中只能直接访问静态成员。
  7. 仔细阅读以下程序,写出程序运行输出的结果。
    在这里插入图片描述
    答:
    In Static
    MyClass()
    20
    MyClass(int)
    10
  8. 仔细阅读以下代码,关于代码描述正确的是© 。
    在这里插入图片描述
    A. 编译通过,输出 10。
    B. 编译不通过,把第 2 行改为 final int value = 10;
    C. 编译不通过,把第 3 行改为 public MyClass(){ value = 10; }
    D. 以上描述都不正确。
    原因:final修饰的属性,如果在构造方法中赋值,那么每一个构造方法都应该有赋值语句。
  9. 仔细阅读以下代码,关于以下程序描述正确的是©。
    在这里插入图片描述
    A. 编译不通过 。
    B. 编译通过;在//1 处加上:mv.value = 200; 则编译不通过。
    C. 编译通过。如果在//1 处加上:mv = new MyValue(); 则编译不通过。
    D. 以上描述都不正确 。
  10. 仔细阅读以下代码,选出正确选项(A)。在这里插入图片描述
    A. 编译通过 。
    B. // 1出错 。
    C. // 2 出错 。
    D. // 3 出错。
    E. // 4 出错 。
    原因:Final所修饰的变量并没有改变值,编译可以通过。
  11. 仔细阅读以下代码,代码中哪些内容是错误的(BC)。 在这里插入图片描述
    A. // 1
    B. // 2
    C. // 3
    D. // 4
    原因:B错误因为抽象方法没有方法体。
    C错误子类覆盖父类方法访问修饰符要么和父类一致要么更宽。
  12. 仔细阅读以下代码,程序是否能编译通过?如果可以,输出运行结果;如果不可以,应该怎样修改?
    在这里插入图片描述
    答:
    可以编译通过,输出结果:
    m1() in Super
    m1(int) in Sub
    m1(double) in Sub
    注意:父类有 m1 方法,并且是 final 的,子类也有 m1 方法,但是子类的 m1 方法和父类的 m1 方法不构成方法覆 盖。
    13 . 仔细阅读以下程序,写出程序运行输出的结果。
    在这里插入图片描述
    答:m1 in Super
    m2 in Sub
    m1 in Sub
    m2 in Sub
    注意:静态方法没有多态。
  13. 下面关于方法声明正确的是(E)。
    A. abstract final void m()
    B. public void final m()
    C. static abstract void m()
    D. private abstract void m()
    E. public static final void m()
  14. 判断以下描述是否正确,正确填 T;否则填 F。
    (1) abstract 可以修饰类、方法、属性(F)
    (2) 抽象类中不一定有构造方法(E)
    (3) 抽象类只能声明引用,不允许单独 new 对象(T)
    (4) 所有类中都可以定义抽象方法(F)
    (5) 子类继承抽象类必须实现抽象类中所有抽象方法(F)
    (6) static 可以修饰属性、方法、代码块(T)
    (7) 静态属性只能用 类名.静态属性名 访问 (F)
    (8) 静态方法可以被本类中的其他方法直接访问(T)
    (9) 静态代码在创建对象时完成静态属性的初始化工作(F)
    (10)final 只能修饰属性、方法、类(F)
    (11)final 修饰的方法不能被继承(F)
    (12)final 修饰的类不能被继承,即没有子类(T)
  15. 把三大特性中的 Shape 类改为抽象类,并把其中的求周长和求面积的方法改为抽象方法。
    演示的代码如下:
package com.txw.test;

abstract class Shape{
    abstract public double girth(); 
    abstract public double area(); 
}
class Circle extends Shape{ 
    private double radius;
    private double pi = 3.1415926;
    
    public Circle(double radius) { 
        this.radius = radius;
    }
    
    public double area() {
        return pi * radius * radius;
    }
    
    public double girth() {
        return 2 * pi * radius; 
    }
}
class Rect extends Shape{ 
    private double a;
    private double b; 
    public Rect(){
        
    } 
    
    public Rect(double a, double b) { 
        this.a = a;
        this.b = b;
    }
    
    public double area() { 
        return a * b;
    }
    
    public double girth() { 
        return 2 * (a + b);
    } 
}
class Square extends Rect{ 
    private double a;
    
    public Square(double a) { 
        super(); 
        this.a = a;
    }
    
    public double area() {
        return a * a;
    }
    
    public double girth() {
        return 4 * a;
    } 
}
  1. 设计一个类 MyClass,为 MyClass 增加一个 count 属性,用来统计总共创建了多少个对象。
    演示的代码如下:
package com.txw.test;

public class MyClass { 
    private int count = 0;
    public MyClass(){
        count ++;
}
public int getCount(){
        return count;
    }
}

6 总结

请简述三个修饰符可修饰的组件与各自的作用。

1. abstract 可以修饰类,方法,被修饰的类只能声明引用不能创建对象,被修饰的方法只有方法声明没有方法实现,只能存在抽象类中。
2. final 可以修饰类,方法,成员变量,局部变量。
		 修饰类:不能被继承。
		 修饰方法:不能被覆盖。
		 修饰成员变量:必须手动赋值,可以通过初始化赋值、动态初始化代码块赋值、构造方法赋值,只能赋值一次,值不能变。
		 修饰局部变量:只能赋值一次,值不能变,基本数据类型值为数据,引用数据类型值为地址。		 
3. static 可以修饰 import , 类, 属性,方法,动态初始化代码块。
		修饰属性:静态属性与对象无关,通过类名直接访问。
		修饰方法:静态方法与对象无关,通过类名直接访问。
		修饰动态初始化代码块:静态初始化代码块,第一次使用一个类时自动调用。
		修饰import:静态引入(import static),可以引入外部的静态资源,使用时不用明确类名。

关于修饰符连用:

1. abstract 不能与 finalstaticprivate一起使用。
2. staticfinal都能修饰属性与方法,可以一起使用,修饰的属性为静态常量。    

如图所示:在这里插入图片描述

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

学无止路

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

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

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

打赏作者

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

抵扣说明:

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

余额充值