13. main()\final关键字\abstract关键字\interface关键字

1. 属性赋值的先后顺序

 /**
 * 测试类中实例变量赋值的先后顺序
 *
 * 1. 类中实例变量赋值有哪些位置:
 * ① 默认初始化  (只能调用一次)
 * ② 显式初始化  (只能调用一次)
 * ③ 构造器中初始化  (只能调用一次)
 * ④ 代码块中赋值
 * ⑤ 通过"对象.属性" 或 "对象.方法"的方法给属性赋值(可以多次调用)
 *
 * 2. 类中实例变量赋值的先后顺序
 *  ① - ② / ④ -  ③ - ⑤
 *
 *  说明:属性的显式赋值与代码块中的赋值的先后顺序完全取决于声明的先后顺序。
 *
 */
public class FieldTest {
   public static void main(String[] args) {
       Order o1 = new Order();
       System.out.println(o1.orderId);
   }

}

class Order{



   int orderId = 1;

   {
       System.out.println("代码块");
       orderId = 2;
   }


   public Order(){
       orderId = 3;
   }
}
  • 练习
//口诀:由父及子,静态先行
class Root{
   static{
      System.out.println("Root的静态初始化块");
   }
   {
      System.out.println("Root的普通初始化块");
   }
   public Root(){
      System.out.println("Root的无参数的构造器");
   }
}
class Mid extends Root{
   static{
      System.out.println("Mid的静态初始化块");
   }
   {
      System.out.println("Mid的普通初始化块");
   }
   public Mid(){
      super();
      System.out.println("Mid的无参数的构造器");
   }
   public Mid(String msg){
      //通过this调用同一类中重载的构造器
      this();
      System.out.println("Mid的带参数构造器,其参数值:"
         + msg);
   }
}
class Leaf extends Mid{
   static{
      System.out.println("Leaf的静态初始化块");
   }
   {
      System.out.println("Leaf的普通初始化块");
   }  
   public Leaf(){
      //通过super调用父类中有一个字符串参数的构造器
      super("尚硅谷");
      System.out.println("Leaf的构造器");
   }
}
public class LeafTest{
   public static void main(String[] args){
      new Leaf();
      System.out.println();
      new Leaf();
   }
}
  • 练习
class Father {
   static {
      System.out.println("11111111111");
   }
   {
      System.out.println("22222222222");
   }

   public Father() {
      System.out.println("33333333333");

   }

}

public class Son extends Father {
   static {
      System.out.println("44444444444");
   }
   {
      System.out.println("55555555555");
   }
   public Son() {
      System.out.println("66666666666");
   }


   public static void main(String[] args) { 
      System.out.println("77777777777");
      System.out.println("************************");
      new Son();
      System.out.println("************************");

      new Son();
      System.out.println("************************");
      new Father();
   }

}

2. main()

/**
 * main()的体会:
 * 1. main()是程序的入口
 * 2. 体会一下具体的关键字
 * 3. 体会main()也可以作为普通的静态方法调用
 * 4. 体会一下main()形参的使用 : 可以通过形参的方式,从控制台输入数据,与程序交互
        以命令行为例: java MainDemo AA 123 hello
 *
 */
public class MainTest {
    public static void main(String[] args) {
        Main.main(null);
    }
}

class Main{
    public static void main(String[] args) {
        System.out.println("hello");
    }
}

3. final关键字

/**
 * final关键字的使用
 *
 * 1. final:最终的
 *
 * 2. final可以用来修饰:类、方法、变量(成员变量、局部变量)
 *
 * 3. final修饰类:说明此类不能被继承!  比如:String\StringBuffer\StringBuilder
 *
 * 4. final修饰方法:说明此方法不能被重写!比如:Object类 getClass()
 *
 * 5. final修饰变量:表示此"变量"不能被修改,即为常量
 *        5.1 final修饰成员变量
 *              可以在哪些位置赋值:显式赋值;代码块中赋值;构造器中赋值;
 *              说明:只能选择上述三个位置之一进行赋值。
 *              标识符的规范中,常量的声明的格式:XXX_YYY_ZZZ
 *              static final的成员变量:全局常量。比如:Math的PI
 *
 *
 *        5.2 final修饰局部变量
 *                 修饰方法内的局部变量:保证在使用此"变量"前,给此"变量"赋值
 *                 修饰方法形参:调用此方法时,给形参赋值。一旦赋值,在方法内就不能修改此"变量"的值。
 *
 */
public class FinalTest {
    public static void main(String[] args) {
        FinalTest test = new FinalTest();
//        test.num3 = 10;

        FinalTest.method1(10);
    }

    final int num = 1;
    final int num1;
    final int num2;
//    final int num3;

    {
//        num = 1;
        num1 = 1;
    }

    public FinalTest(){
        num2 = 2;
    }
    public FinalTest(String s){
        this();
    }

    public void method(){
        final int NUM = 1;
//        NUM = 2;
        System.out.println(NUM);
    }

    public static void method1(final int NUM){
//        NUM = 1;
        System.out.println(NUM);
    }

}

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

final class A{

}
//class B extends A{
//
//}

class C{
    public final void method(){

    }
}

class D extends C{
//    public void method(){
//
//    }
}
  • 笔试题
    13. main()\final关键字\abstract关键字\interface关键字

4. abstract关键字:抽象类与抽象方法

/**
 * abstract关键字的使用:
 *  * abstract class Account{
 *     double balance;//余额
 *  *     public abstract void withdraw(double amt);//取钱的操作
 *  *     public void deposit(double amt){}
 *  * }
 *  * class SavingAccount extends Account{}//储蓄账户
 *  * class CheckingAccount extends Account{} //信用卡账户
 *  * ...
 *  *  *class Customer{
 *     Accoun acct;
 *     public void setAccount(Account acct){
 *         this.acct = acct;
 *     }
 *}
 *  *  * 1. abstract:抽象的
 * 2. abstract可以用来修饰:类、方法
 *  * 3. abstract修饰类:抽象类
 *      > 不能实例化
 *      > 抽象类中可以没有抽象方法;但是抽象方法所属的类一定是抽象类。
 *  * 4. abstract修饰方法:抽象方法 (此方法仅保留了方法的声明,没有方法具体的实现,即没有方法体)
 *      > 实际开发中,抽象方法就需要被子类重写。
 *      > 子类继承抽象类之后,必须重写所有的抽象方法,方可实例化。
 *        子类继承抽象类之后,如果没有重写父类中的所有的抽象方法,则子类仍为一个抽象类。
 *  *  */
  • 代码举例
public class AbstractTest {
    public static void main(String[] args) {
//        Person p1 = new Person();
//        p1.eat();

        Student s1 = new Student();
        s1.eat();
        s1.walk();
    }

}

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

abstract class Person extends Creature{
    String name;
    int age;

    public abstract void eat();

    public void walk(){
        System.out.println("人:走路");
    }
}

class Student extends Person{
    String major;

    public void eat(){
        System.out.println("学生:吃饭");
    }
    public void walk(){
        System.out.println("学生:走路");
    }

    @Override
    public void breath() {
        System.out.println("学生应该呼吸新鲜空气");
    }
}

abstract class Worker extends Person{

}
  • 补充说明
  • 不能用abstract修饰变量、代码块、构造器;
  • 不能用abstract修饰私有方法、静态方法、final的方法、final的类。
  • 抽象的应用:模板方法的设计模式
/**
 * 抽象类的应用:模板方法的设计模式
 *
 */
public class TemplateTest {

    public static void main(String[] args) {
        Template temp = new SubTemplate1();
        temp.spendTime();
    }

}

abstract class Template{

    /**
     * 计算某段代码执行所需要的花费的时间
     */
    public void spendTime(){

        long start = System.currentTimeMillis();

        //执行某段代码
        this.code();

        long end = System.currentTimeMillis();

        System.out.println("花费的时间为:" + (end - start));

    }

    protected abstract void code();

}

class SubTemplate1 extends Template{

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

            if(isFlag){
                System.out.println(i);
            }
            isFlag = true;

        }

    }
}

class SubTemplate2 extends Template{

    @Override
    protected void code() {

    }
}
  • 练习1
/**
 * 几何图形类
 *
 */
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 String getColor() {
        return color;
    }

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

    public double getWeight() {
        return weight;
    }

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

    public abstract double findArea();
}


public class Circle extends GeometricObject {
    private double radius;
    public Circle(double radius,String color,double weight){
        super(color,weight);
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    public double findArea(){
        return 3.14 * radius * radius;
    }
}

public class MyRectangle extends GeometricObject {

    private double width;//宽
    private double height;//高

    public MyRectangle(double width, double height,String color, double weight) {
        super(color, weight);
        this.width = width;
        this.height = height;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
    public double findArea(){
        return width * height;
    }

}



/**
 * 定义一个测试类GeometricObjectTest,
 * 编写equalsArea方法测试两个对象的面积是否相等(注意方法的参数类型,利用动态绑定技术),
 * 编写displayGeometricObject方法显示对象的面积(注意方法的参数类型,利用动态绑定技术)。
 */
public class GeometricObjectTest {
    public static void main(String[] args) {
        GeometricObjectTest test = new GeometricObjectTest();

        Circle circle = new Circle(2.3, "red", 1.0);
        test.displayGeometricObject(circle);

        MyRectangle myRectangle = new MyRectangle(3.4, 2.3, "blue", 2.0);
        test.displayGeometricObject(myRectangle);

        test.equalsArea(circle,myRectangle);
    }

    public void equalsArea(GeometricObject o1,GeometricObject o2){
        boolean isEqual = o1.findArea() == o2.findArea();
        if(isEqual){
            System.out.println("面积相等");
        }else{
            System.out.println("面积不相等");
        }
    }

    public void displayGeometricObject(GeometricObject o ){
        System.out.println("几何图形的面积为:" + o.findArea());
    }
}
  • 练习2
    13. main()\final关键字\abstract关键字\interface关键字
public abstract class Employee {
    private String name;
    private int id;
    private double salary;//工资

    public Employee(String name, int id, double salary) {
        this.name = name;
        this.id = id;
        this.salary = salary;
    }

    public Employee() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public abstract void work();
}



public class Manager extends Employee {

    private double bonus;//奖金

    public Manager() {
    }

    public Manager(double bonus) {
        this.bonus = bonus;
    }

    public Manager(String name, int id, double salary, double bonus) {
        super(name, id, salary);
        this.bonus = bonus;
    }

    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    @Override
    public void work() {
        System.out.println("管理者监督员工的工作");
    }
}


public class CommonEmployee extends  Employee{

    public CommonEmployee(String name, int id, double salary) {
        super(name, id, salary);
    }

    public CommonEmployee() {

    }

    @Override
    public void work() {
        System.out.println("普通员工在一线工作");
    }
}
package com.atguigu.exer1;


public class EmployeeTest {
    public static void main(String[] args) {
        Manager manager = new Manager("Tom", 1001, 3000, 2000);

        manager.work();

        CommonEmployee commonEmployee = new CommonEmployee();
        commonEmployee.work();
    }
}
  • 练习3
    13. main()\final关键字\abstract关键字\interface关键字
/**
 *
 * 定义一个Employee类,该类包含:
 * private成员变量name,number,birthday,其中birthday 为MyDate类的对象;
 * abstract方法earnings();
 * toString()方法输出对象的name,number和birthday。
 *
 */
abstract class Employee {
    private String name;//员工姓名
    private String number;//员工工号
    private MyDate birthday;//员工生日

    public Employee() {
    }

    public Employee(String name, String number) {
        this.name = name;
        this.number = number;
    }

    public Employee(String name, String number, MyDate birthday) {
        this.name = name;
        this.number = number;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNumber() {
        return number;
    }


    public MyDate getBirthday() {
        return birthday;
    }

    /**
     * 发工资方式
     * @return 返回员工的工资
     */
    public abstract double earnings();

    @Override
    public String toString() {
        return "{" +
                "name='" + name + '\'' +
                ", number='" + number + '\'' +
                ", birthday=" + birthday.toDateString() +
                '}';
    }
}

package com.atguigu.exer2;

/**
 *
 * MyDate类包含:
 * private成员变量year,month,day ;
 * toDateString()方法返回日期对应的字符串:xxxx年xx月xx日
 *
 */
public class MyDate {
    private int year;
    private int month;
    private int day;

    public MyDate() {
    }

    public MyDate(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public String toDateString() {

        return year + "年" + month + "月" + day + "日";
    }

}



/**
 * 定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处理。
 * 该类包括:private成员变量monthlySalary;
 * 实现父类的抽象方法earnings(),该方法返回monthlySalary值;
 * toString()方法输出员工类型信息及员工的name,number,birthday。
 *
 * 月结工资
 */
public class SalariedEmployee extends Employee {

    private double monthlySalary;//月工资

    public SalariedEmployee() {
    }

    public SalariedEmployee(String name, String number, double monthlySalary) {
        super(name, number);
        this.monthlySalary = monthlySalary;
    }

    public SalariedEmployee(String name, String number, MyDate birthday, double monthlySalary) {
        super(name, number, birthday);
        this.monthlySalary = monthlySalary;
    }

    /**
     * 返回员工工资,月结
     * @return
     */
    @Override
    public double earnings() {
        return monthlySalary;
    }

    public String toString(){
        return "SalariedEmployee" + super.toString() ;
    }
}


/**
 *
 * 参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的员工处理。该类包括:
 * private成员变量wage和hour;
 * 实现父类的抽象方法earnings(),该方法返回wage*hour值;
 * toString()方法输出员工类型信息及员工的name,number,birthday。
 *
 *
 */
public class HourlyEmployee extends Employee {
    private double wage;//单位小时的工资
    private int hour;//月工作小时数

    public HourlyEmployee() {
    }

    public HourlyEmployee(String name, String number, MyDate birthday, double wage, int hour) {
        super(name, number, birthday);
        this.wage = wage;
        this.hour = hour;
    }

    /**
     * 返回员工的月工资
     * @return
     */
    @Override
    public double earnings() {
        return wage * hour;
    }

    public double getWage() {
        return wage;
    }

    public void setWage(double wage) {
        this.wage = wage;
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public String toString(){
        return "HourlyEmployee" + super.toString();
    }
}


import java.util.Calendar;
import java.util.Scanner;

/**
 * 定义PayrollSystem类,
 * 创建Employee变量数组并初始化,该数组存放各类雇员对象的引用。
 * 利用循环结构遍历数组元素,输出各个对象的类型,name,number,birthday,以及该对象生日。
 * <p>
 * 当键盘输入本月月份值时,如果本月是某个Employee对象的生日,还要输出增加工资信息。
 *
 */
public class PayrollSystem {

    Employee[] employees = new Employee[2];

    public static void main(String[] args) {
        PayrollSystem test = new PayrollSystem();
        test.employees[0] = new SalariedEmployee("江学振", "1001", new MyDate(1995, 3, 4), 20000);
        test.employees[1] = new HourlyEmployee("荣鹏", "1002", new MyDate(1996, 4, 3), 100, 176);

        //方式1:
//        Scanner scan = new Scanner(System.in);
//        System.out.println("请输入当前的月份:");
//        int month = scan.nextInt();

        //方式2:
        Calendar calendar = Calendar.getInstance();
        int month = calendar.get(Calendar.MONTH) + 1;
//        System.out.println(month);

        for (int i = 0; i < test.employees.length; i++) {
            System.out.println(test.employees[i]);
            double bonus = 0;
            if (month == test.employees[i].getBirthday().getMonth()) {
                System.out.println("生日快乐!奖100块钱");
                bonus = 100;
            }

            System.out.println("员工工资为:" + (test.employees[i].earnings() + bonus));
        }
    }
}

5. interface关键字:接口

/**
 * 接口的使用
 *
 * 1. 我们使用interface定义接口 (复习:我们使用class定义类)
 * 2. 接口内部可以定义的结构:
 *       jdk7及之前:
 *            全局常量:public static final  。 在实际声明时,此修饰可以省略
 *            抽象方法:public abstract 。 在实际声明时,此修饰可以省略
 *       ********************************************
 *       jdk8新特性:
 *            静态方法(有方法体)、默认方法(有方法体)
 *       jdk9新特性:
 *           私有方法
 *
 *    说明:接口中不存在构造器的!
 *          接口不能实例化
 *
 * 3. 类与接口之间是实现(implements)关系,而且类可以实现多个接口。
 *    格式:class A extends B implements C
 *     A相较于B来讲,称为:子类
 *     A相较于C来讲,称为:实现类
 *
 * 4. 如果实现类实现了接口中的所有的抽象方法,则此实现类方可实例化
 *    如果实现类没有实现接口中的所有的抽象方法,则此实现类仍是一个抽象类
 *
 * 5. 接口与接口之间是继承关系,而且可以多继承。
 *
 */
public class InterfaceTest {
    public static void main(String[] args) {
        System.out.println(Flyable.MIN_SPEED);
        System.out.println(Flyable.MAX_SPEED);

//        Flyable.MAX_SPEED = 7800;
    }
}

interface Flyable{
    // 属性
    public static final int MIN_SPEED = 1;
    int MAX_SPEED = 7900;

    //方法
//    public abstract void fly();
    void fly();
}

interface Attackable{

    void attack();

}

class Plane implements Flyable{

    @Override
    public void fly() {
        System.out.println("飞机可以飞~");
    }
}

abstract class Bullet implements Flyable,Attackable{

}

//**************************
interface AA{
    void method1();
}

interface BB{
    void method2();
}
interface CC extends AA,BB{

}

class DD implements CC{
    public void method1(){

    }
    public void method2(){

    }
}
  • 体现接口是一种规范
    13. main()\final关键字\abstract关键字\interface关键字
/**
 *
 * 体会接口的规范!
 *
 * 接口,也存在多态性!
 *
 */
public class USBTest {

    public static void main(String[] args) {
        Printer printer = new Printer();
        operate(printer);

        operate(new KeyBoard());
    }

    public static void operate(USB usb){ //USB usb = new Printer();

        System.out.println("========检测外部设备=========");

        usb.start();

        System.out.println("==========具体的数据传输过程===========");

        usb.stop();
    }

}


interface  USB{
    //常量:定义的USB的尺寸等

    void start();

    void stop();
}

class Printer implements USB{//打印机

    @Override
    public void start() {
        System.out.println("打印机开始工作");
    }

    @Override
    public void stop() {
        System.out.println("打印机结束工作");
    }
}

class KeyBoard implements USB{

    @Override
    public void start() {
        System.out.println("键盘开始工作");
    }

    @Override
    public void stop() {
        System.out.println("键盘结束工作");
    }
}

6. 了解:深拷贝与浅拷贝

class Customer{
    public Customer(Account acct, int age) {
        this.acct = acct;
        this.age = age;
    }

    public Customer() {
    }

    Account acct;
    int age;


}

class Account{
    double balance;

    public Account(double balance) {
        this.balance = balance;
    }

    public Account() {
    }
}

public class CopyTest {
    public static void main(String[] args) {
        //引用复制
        Customer c1 = new Customer();
        Customer c2 = c1;


        //对象复制之浅拷贝
        Account acct1 = new Account(2000);
        Customer c3 = new Customer(acct1,20);
        Customer c4 = new Customer(acct1,20);

        //对象复制之深拷贝
        Account acct2 = new Account(2000);
        Customer c5 = new Customer(acct2,20);

    }
}
上一篇:分块算法学习笔记


下一篇:牛客小白月赛44 E. 变异蛮牛(树形DP)