文章目录
Java SE从入门到放弃(十四)之代码块、final关键字以及抽象类和抽象方法
一、我们熟悉的main()方法
-
main()是程序的入口
-
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]);
}
}
}
- 可以通过控制台给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万美元!!");
}
}
如果这些对你有帮助的话,可不可以帮我一键三连呢?