Java SE从入门到放弃(十四)

Java SE从入门到放弃(十四)之代码块、final关键字以及抽象类和抽象方法

一、我们熟悉的main()方法

  1. main()是程序的入口

  2. main()看作是一个普通的静态方法

public class MainTest {

	public static void main(String[] args) {//程序的入口
		Main.main(new String[10]);
	}
}

class Main {
	public static void main(String[] args) {//看作是普通的静态方法
		for(int i = 0;i < args.length;i++){
			args[i] = "args_" + i;
			System.out.println(args[i]);
		}
	}
}
  1. 可以通过控制台给main()的形参进行赋值操作

二、类的成员之四:代码块

类的成员之四:代码块(或初始化块)
 * 
 * 1. 代码块如果有修饰的话,只能使用static
 * 2. 代码块的分类:静态代码块  vs 非静态代码块
 * 
 * 3. 静态代码块的使用
 * 	  > 内部可以声明执行语句
 *    > 随着类的加载而执行
 *    > 由于类的加载只执行一次,所以静态代码块也只执行一次
 *    > 作用:用来初始化类的基本信息:静态属性
 *    > 可以在内部调用类的静态结构:属性、方法。不能调用非静态的属性或方法
 *    > 如果在一个类中声明了多个静态代码块,则按照声明的先后顺序执行。
 *    > 静态代码块的执行要先于非静态代码块的执行
 * 
 * 
 * 4. 非静态代码块的使用
 * 	  > 内部可以声明执行语句
 * 	  > 随着对象的创建而执行
 *    > 每创建一个对象,就执行一次
 *    > 用来初始化对象的基本信息:非静态属性
 *    > 可以在内部调用类的静态结构和非静态的结构:属性、方法
 *    > 如果在一个类中声明了多个非静态代码块,则按照声明的先后顺序执行。
 * 
class Person{
	
	String name;
	int age;
	static String nation = "CHN";
	
	public Person(){
		
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	//静态代码块
	static{
		//执行语句
		int i = 10;
		System.out.println(i + ":静态");
		//不能调用非静态的结构
//		name = "Tom";
//		eat();
		//调用静态结构
		System.out.println(nation);
		showNation();
	}
	
	static{
		System.out.println("我是静态代码块3");
	}
	static{
		System.out.println("我是静态代码块2");
	}
	
	
	//非静态代码块
	{
		System.out.println("我是非静态代码块3");
	}
	{
		//执行语句
		int i = 10;
		System.out.println(i + ":非静态");
		//可以调用静态结构和非静态结构
		name = "Tom";
		eat();
		showNation();
	}
	
	{
		System.out.println("我是非静态代码块2");
	}
	
	
	
	public void eat(){
		System.out.println("人吃饭");
	}
	//随着类的加载而加载
	public static void showNation(){
		System.out.println("我是一个中国人");
	}
	
	
}

三、属性赋值的先后顺序

1. 属性赋值的位置

 * 可以给类的非静态的属性赋值的位置有:
 * 
 * ① 默认初始化
 * ② 显式初始化
 * ③ 代码块中初始化
 * ④ 构造器中初始化
 * ⑤ 创建了对象以后,通过“对象.属性”或"对象.方法"的方式,给属性赋值

2. 赋值的先后顺序

执行的先后顺序:
 * ① - ②/③ - ④ - ⑤ 
 * 
 * 说明:② 和 ③执行的先后顺序,取决于二者声明的先后顺序。

四、final关键字的使用

1. final:最终的
 * 
2. final可以用来修饰:类、方法、变量(包含属性、局部变量)

1. final修饰类

final修饰类:此类不可以被继承。

  •   比如:String\StringBuffer\StringBuilder
    

2. final修饰方法

final修饰方法:此方法不可以被重写

  •   比如:Object中的getClass()
    

3. final修饰变量

final修饰变量:表明此变量,一旦赋值以后,此值就不能被修改。即为一个常量。
 * 		① final修饰属性:
 * 			在哪些位置可以给常量赋值?① 显式初始化 ②代码块中初始化 ③ 构造器中初始化 
 *      开发中的应用场景:我们常在项目的代码中会使用一些数值,一般我们会将这些数值定义为常量,在代码中
 *       使用这些常量。
 *      ② final修饰局部变量中的形参: 1. 调用此方法时,给形参常量赋值  
 *      					2.一旦赋值,在方法内可以使用此形参常量,但是不能给形参常量再赋值。
 
 static final 修饰成员变量的话:全局变量。比如:Math里的PI

代码测试:

public class FinalTest {
	
	
	final int NUM = 1;//常量
	
	final int UP = 0;
	final int DOWN;
	final int LEFT;
	final int RIGHT;
	
	{
		DOWN = 1;
	}
	
	public FinalTest(){
		LEFT = 2;
		RIGHT = 3;
	}
	
	public FinalTest(int i,int j){
		LEFT = i;
		RIGHT = j;
	}
	
	public void test(){
//		num = 2;
	}
	
	
	public void test1(){
		final int COUNT = 1;
//		COUNT = 2;
	}
	
	public void test2(final int num){
		System.out.println(num);
//		num++;
	}
	
}

final class A{
	
}
//The type B cannot subclass the final class A
//class B extends A{
//	
//}

//class SubString extends String{
//	
//}

class C{
	public final void test(){
		
	}
}

class D extends C{
	// Cannot override the final method from C
//	public void test(){
//		
//	}
}

4. 面试题

在这里插入图片描述

  • 题目一:编译不通过。
  • 题目二:编译通过,运行也通过

五、抽象类与抽象方法

1. 引入

在这里插入图片描述

2. 抽象类 与 抽象方法

   1. abstract:抽象的
 * 
 * 2. abstract可以用来修饰:类、方法
 * 
 * 3. abstract 修饰类:抽象类
 * 		> 不能实例化
 * 		> 抽象类中仍然存在构造器。  --->只要是类,内部一定有构造器
 * 			>此时抽象类中的构造器,便于子类实例化时使用。
 * 
 * 4. abstract 修饰方法:抽象方法 :即使用abstract修饰,且没有方法体。
 * 		> 抽象类中可以没有抽象方法的
 * 		> 抽象方法所在的类必须是抽象类
 * 		> 抽象类的子类必须重写其父类中的所有的抽象方法,方可实例化。
 * 		> 抽象类的子类如果没有重写其父类中的所有的抽象方法,则此子类仍然为一个抽象类。
 * 

3. 代码体现一

abstract class Creature{//生物类
	public abstract void breath();//呼吸
}

abstract class Person extends Creature{ //抽象类
	
	String name;
	int age;
	
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	//抽象方法
	public abstract void eat();
	
	public abstract void walk();
	
}

class Student extends Person{
	
	public Student() {
		super();
	}

	public Student(String name, int age) {
		super(name, age);
	}

	public void eat(){
		System.out.println("学生:多吃有营养的食物");
	}
	
	public void walk(){
		System.out.println("学生:背着书包上学");
	}

	@Override
	public void breath() {
		System.out.println("学生:呼吸新鲜没有雾霾的空气");
	}
}

abstract class Worker extends Person{
	public void eat(){
		System.out.println("工人:多吃肉,有劲");
	}
	
//	public void walk(){
//		System.out.println("工人:扛着工具走路");
//	}
}

4. 代码体现二

 * abstract class Account{//账户:抽象类
 * 		int balance;//余额
 * 
 * 		public abstract void withdraw(double amt);
 * }
 * 
 * class SavingAccount extends Account{ //储蓄账户
 * 
 * }
 * 
 * class CheckAccount extends Account{//信用卡账户
 * 
 * }
 * 
 * 。。。。
 * class Customer{
 * 	
 * 		Account acct;
 * 
 * 		public void setAccount(Account acct){
 * 			this.acct = acct;
 * 		}
 * }

5. 代码体现三

public abstract class GeometricObject {
    protected String color;
    protected double weight;

//    protected GeometricObject(){
//    	
//    }

    protected GeometricObject (String color,double weight){
        this.color = color;
        this.weight = weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    //求面积的方法
    public abstract double findArea();
}

6. abstract使用的注意事项

 *  不能用abstract修饰变量、代码块、构造器;
 *  
 *  不能用abstract修饰私有方法、静态方法、final的方法、final的类。

7. 抽象性的应用:模板方法的设计模式

当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。

换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现。这就是一种模板模式。

举例一:

public class TemplateTest {
	public static void main(String[] args) {
		Template t = new SubTemplate();
		t.spendTime();
	}
}

abstract class Template{
	
	//不确定的部分:使用抽象方法
	public abstract void code();
	
	//计算code()中的代码执行花费的时间
	public void spendTime(){
		
		long start = System.currentTimeMillis();
		
		code();
		
		long end = System.currentTimeMillis();
		
		System.out.println("花费的时间为:" + (end - start));
	}
}

class SubTemplate extends Template{

	@Override
	public void code() {
		
		for(int i = 2;i <= 100000;i++){
			boolean isFlag = true;
			for(int j = 2;j <= Math.sqrt(i);j++){
				if(i % j == 0){
					isFlag = false;
					break;
				}
			}
			
			if(isFlag){
				System.out.println(i);
			}
		}
		
	}
	
}

举例二:

//抽象类的应用:模板方法的设计模式
public class TemplateMethodTest {

	public static void main(String[] args) {
		BankTemplateMethod btm = new DrawMoney();
		btm.process();

		BankTemplateMethod btm2 = new ManageMoney();
		btm2.process();
	}
}
abstract class BankTemplateMethod {
	// 具体方法
	public void takeNumber() {
		System.out.println("取号排队");
	}

	public abstract void transact(); // 办理具体的业务 //钩子方法

	public void evaluate() {
		System.out.println("反馈评分");
	}

	// 模板方法,把基本操作组合到一起,子类一般不能重写
	public final void process() {
		this.takeNumber();

		this.transact();// 像个钩子,具体执行时,挂哪个子类,就执行哪个子类的实现代码

		this.evaluate();
	}
}

class DrawMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要取款!!!");
	}
}

class ManageMoney extends BankTemplateMethod {
	public void transact() {
		System.out.println("我要理财!我这里有2000万美元!!");
	}
}

如果这些对你有帮助的话,可不可以帮我一键三连呢?
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值