Java基础 Day11

final修饰符

1. 使用final修饰类、方法和属性
  • final修饰符可用来修饰类或类中的成员

  • 被final修饰的类成为最终类,不能再被子类所继承

  public final class FinalClass {}
  • 面试题:为什么String是final的?

  • final修饰的类称为终类,不可以被继承

  • 如果String可以被继承,那么开发者可以开发自己的String的子类,并且可以重写String中的各类方法,在后续的程序中,可以直接传入自己开发的String的子类对象,执行的是开发者重写的String方法的逻辑

  • 像String这样在整个Java中被广泛应用的类,其方法逻辑如果被修改,会对程序的稳定性造成较大的隐患,因此,设计者将String设计为final的,不允许被继承

  • 被final修饰的方法成为最终方法,不能再被子类的方法所覆盖。例如:

  public class FinalMethodClass {
  
  	public final void method() {} 
  
  }
  • 被final修饰的属性称为常量,其值一旦赋予,便不能再被修改。例如:
  public class FinalFieldClass {
  
  	public final int COUNTER = 100; //常量的声明通常使用大写
  
  }
2. 静态常量
  • 大多数情况下,static与final一起使用以修饰一个公用常量。例如:
  public static final int MAX_NUM = 65535;
  
  public static final String COMPANY_NAME="小米";
  • 这种常量可以在程序的任何位置被直接访问,且值不会被篡改

  • 静态常量的命名规则:

    • 所有字母都大写
    • 单词与单词之间,使用下划线分割
    • 不要怕名字太长,要把这个变量的作用说清楚
3. 空final变量
  • 在声明常量时,可以暂时不为其指定初始值,称为空final变量

  • 空final变量的初始值必须在构造器中指定。例如:

  public class FinalFieldClass {
  
  	public final int counter;
  	public FinalFieldClass(int n) {
      	counter = n;}
  }
  • 空final变量不能用static来修饰。

抽象类(abstract class)

  • 抽象类与具体类

    • 具体类 — 对现实世界一种实体的抽象定义 - 比如猫
    • 抽象类 — 对现实世界一种类型的多种实体的统一抽象定义 - 比如宠物
  • 例如:

    • Pet类应定义为抽象类
    • Bird类应定义为具体类
  • abstract关键字

    • 可用于修饰类和方法
    • 修饰类时,该类是抽象类
    • 修饰方法时,该方法是抽象方法,没有方法体
  • 抽象类中可声明抽象方法

  • 另一种抽象类的定义方式:包含抽象方法的类就是抽象类

  • 示例:

  public abstract class Pet {
  
  	public abstract void speak();
  	……
  
  }
  • 抽象类中可以包含的成员包括:

    • 属性
    • 构造器
    • 具体方法
    • 抽象方法
  public abstract class Pet {
      private String name;
      private int age;
      private int weight;
  
      public Pet(String name, int age, int weight) {
          this.name = name;
          this.age = age;
          this.weight = weight;
      }
      public String getName() {
      	return name;
      }
      public void setName(String name) {
      	this.name = name;
      }
      public abstract void speak();
      public abstract void eat();
  }
  • 具体类继承抽象类:

    • 抽象类不能被实例化
      • 抽象类的抽象方法没有被实现
      • 实例与现实世界中一个具体的事物相对应,抽象类没有直接对应的具体事物
    • 子类(具体类)可继承抽象父类 ,实现抽象方法
    • 具体子类适用抽象父类的多态
  public class Bird extends Pet {
  	private String type;
  
      public Bird(String name, int age, int weight, String type) {
          super(name, age, weight);
          this.type = type;
      }
  
      public String getType() {
      	return type;
      }
      public void speak() {
      	System.out.println("布谷布谷...");
      }
      public void eat() {
      	System.out.println("Eating...");
      }
  }
  
  public class TestAbstract {
      public static void main(String args[]) {
      	Pet pet = new Bird("小布", 1, 100, "布谷鸟");
      	pet.speak();
      }
  }
  • 常见问题:

    • 抽象类里一定含有抽象方法?不一定
    • 含有抽象方法的类一定是抽象类?一定是
    • 抽象类里可以定义属性和方法?可以
    • 抽象类里可以定义构造方法?可以
    • 抽象类可以创建对象?不可以
    • 抽象方法可以被private/final/static分别修饰?都不行,抽象方法只有被子类重写,才能够实际执行,被private/final/static修饰的方法都不能被重写,因此不能用它们修饰抽象方法
    • 抽象类可以被final修饰?不可以,抽象类不能被实例化,需要被继承才能实例化。final修饰会限定抽象类不能被继承
    • 抽象类是否可以继承抽象类?
      • 抽象类可以继承抽象类,可以实现其中定义的一部分抽象方法,留下另一部分抽象方法由具体子类实现

中场总结:

  • 引用类型转换

    • a instanceof Person:判断a引用的是否是Person或其子类的对象
    • Student s=(Student)p;
  • 对象的关联

    • 一个类中的某个属性的类型是另一个类
    • 当实例化一个对象时,它的一个属性值是另一个对象的地址,也就是A对象通过属性关联了B对象
  • static(静态的)

    • static修饰属性:静态变量,可以通过类名.变量名直接访问,所有地方访问的是同一个静态变量
    • static修饰方法:静态方法,可以通过类名.方法名直接调用,常用于各种工具类的方法
    • static修饰代码块:静态代码块(静态初始化器),用于初始化本类的静态成员(变量)
      • 在类加载时执行1次
    • 题目:
      • 静态代码块和构造代码块的区别
        • 静态代码块使用static修饰的代码块,static{},又称为静态初始化器,用于初始化本类的静态成员,在类加载时执行一次
        • 构造代码块是声明在类中的{},用于初始化本类的实例成员,在每次创建该类的实例时执行1次
      • 构造代码块和构造器什么区别
        • 构造代码块先于构造器执行
        • 构造器可以分为无参的和带参的,带参构造器可以接收用户创建对象时传入的参数,为对应的属性赋值
        • 构造代码块不能接收参数,可以将所有构造器都要执行的逻辑放入构造代码块中
          • 构造代码块{ 逻辑1,逻辑2 }
          • 构造器1{逻辑3}
          • 构造器2{逻辑4}
          • 构造器3{逻辑5}
  • final

    • 修饰类-> 终类 -> 不能被继承
    • 修饰方法 -> 最终方法 -> 不能被重写
    • 修饰属性 -> 常量 -> 赋值后值不能被修改
      • 一般和static搭配,成为静态常量
        • 可以在程序任意位置被访问,且不会被修改
        • 命名规范:所有单词都大写,单词与单词之间使用下划线分割
  • 抽象类

    • 含有抽象方法的类是抽象类/使用 abstract修饰的类就是抽象类
    • 抽象方法:
      • 使用 abstract修饰的方法
      • 没有方法体
      • 不能被private/static/final修饰
    • 抽象类不能被实例化
    • 一个具体类继承了抽象类,必须实现抽象类中定义的所有抽象方法
    • 抽象类只能实例化它的具体子类(多态引用)

接口

1. 接口的概念
  • 接口的用途是用来定义现实世界不同类型事物的共同行为特征。

  • 例如:

    • 飞行特征(包括起飞,飞行、着陆等行为)是鸟和飞机所共有的。
    • 鸟和飞机可定义为具体类
    • 它们的共同行为特征可被定义在接口中
  • 接口中所有方法均为抽象方法

  • 示例:

  public interface Flyer {    
  	public void takeoff();
  	    	……    }}
2. 接口的成员
  • 接口可以包含以下成员:

    • 属性

      • 接口中的所有属性均被视静态常量。例如,下面几种方式的声明是等效的:
  int num = 10;public int num = 10;
  public static final int num = 10;
  • 抽象方法

    • 接口中所有方法均为抽象方法。例如,下面两种方式的声明是等效的:
  public abstract void takeoff();
  public void takeoff();
  • 具体方法

    • JDK1.8中为了加强接口的能力,使得接口可以存在具体的方法,前提是方法需要被default或static关键字所修饰
  public interface Flyer {	
  	public abstract void takeoff();	
  	public void land();	
  	public void fly();
  }
3. 具体类实现接口
  • 接口不能被实例化
  • 具体类(子类)可以实现接口(父类) ,并实现接口中的抽象方法
  • 具体类适用父接口的多态
  • Java语言允许一个类同时实现多个接口
  • 子类必须提供所有父接口中所有方法的实现
public class Bird implements Flyer {
    private String type;

    public Bird() {}

    public String getType() {
    	return type;
    }

    public void takeoff() {
    	System.out.println("I'm taking off...");
    }
    public void land() {
    	System.out.println("I'm landing...");
    }
    public void fly() {
    	System.out.println("I'm flying...");
    }
}

public class TestInterface {
    public static void main(String args[]) {
    	Bird bird = new Bird();
    	bird.takeoff();

        Flyer flyer = new Bird();
    	flyer.takeoff();
    }
}
4. 具体类-抽象类-接口
  • 很多情况下:
    • 抽象类实现接口,并可实现接口中的部分方法
    • 具体类继承抽象类,并实现所有抽象方法

请添加图片描述

  • 同时继承父类并实现接口

    • 一个类可以同时继承父类并实现接口

请添加图片描述

5. 抽象类和接口的区别
  • 抽象类是类,接口不是类
  • 一个类继承抽象类使用extends关键字,实现接口使用implements关键字
  • 一个接口可以使用extends关键字继承另一个接口
  • 一个类仅能继承一个抽象类,但是可以实现多个接口
  • 抽象类的目的是延展类继承结构,接口是为了注入更多的特性
6. 接口的有点
  • 模板
  • 约束

内部类

1. 在类中定义类

方法内部类
  • 方法内定义类
  • 类里可以定义所有的非静态信息以及静态常量
  • 可以进行正常的继承和实现
  • 不能被public/默认来修饰但是可以被final/abstract来修饰
  • 可以拿到外部类所有信息
  • 只能拿到本方法的常量信息
  • 创建对象只能在本方法里创建对象
public class InnerDemo1{

    public static void main(String[] args){
        //外部类对象调用m方法执行里面创建内部类语句
        newOuter1().m();
    }

}

//外部类
class Outer1{
    //属性
    intk=10;
    //方法
    public void m(){
        intj=1;//再jdk1.8之前需要手动写上final才是常量
        //在jdk1.8及其以后版本不写fianl底层也会添加final
        //j=2;//没有检测到内部类之前还是正常变量操作,但是一旦检测
        //到方法内部类需要加上final
        //方法内部类
        //可以定义所有的非静态信息以及静态常量
        //可以进行正常的继承和实现
        //不能被public以及默认修饰类
        //可以被final/abstract来修饰
        //内部类可以获取外部类所有的信息
        //方法内部类只能获取本方法里的常量信息
        class Inner1 extends Object implements Cloneable{

            static final int i=1;
            public void n(){
                System.out.println(k);
                System.out.println(j);
            }
        }
        //创建方法内部类对象
        Inner1 in=new Inner1();
        in.n();
    }

}
成员内部类
  • 类内方法外定义类

  • 定义所有的非静态信息以及静态常量

  • 正常继承和实现

  • 被访问权限修饰符以及final和abstract来修饰

  • 拿到外部类的所有信息

    Outer1.Inner1 inner1=new Outer1().new Inner1();

public class InnerDemo1{

    public static void main(String[] args){
		// 创建成员内部类对象
        // 声明---内部类
        Outer1.Inner1 inner1=new Outer1().newInner1();
    }
}

//外部类
class Outer1{
    //属性(成员变量)
    inti=1;
    //创建成员内部类对象---外部类的属性
    //Inner1in1=newInner1();
    //成员内部类
    //可以定义所有的非静态信息以及静态常量
    //可以进行正常的继承和实现
    //支持所有的访问权限修饰符来修饰以及final和abstract
    //可以拿到外部类所有的信息
    class Inner1 extends Object implements Cloneable{

        static final int j=10;
        public void n(){
        	System.out.println(i);
        	m();
        }
    }

    //方法(成员方法)
    public void m(){}
}
静态内部类
  • 类内方法外定义被static修饰的类

  • 定义所有信息

  • 正常继承和实现

  • 被访问权限修饰符以及final和abstract来修饰

  • 拿到外部类的静态信息

    Outer2.Innner2 innner2=new Outer2.Innner2();

public class InnerDemo2{

	public static void main(String[] args){
        //创建静态内部类对象
        Outer2.Innner2innner2=newOuter2.Innner2();
    }

}

//外部类
class Outer2{
    //属性
    static int i=1;
    //静态内部类
    //定义所有的信息
    //进行继承和实现
    //可以被访问权限修饰符以及final和abstract
    //只能获取外部类的所有静态信息
    static class Innner2 extends Object implements Cloneable{
        static final int j=10;
        public void n(){
        	System.out.println(i);
    	}
	}

	//方法
	public void m(){}
}
匿名内部类
  • 用于继承类/实现接口来重写(抽象)方法成创建对象使用

  • 只要类可以有被继承/接口可以被实现都可以有匿名内部类形式

  • 匿名内部类主要适用的场景就是传参,只能使用一次

public class InnerDemo3{

    public static void main(String[] args){
        //{}区域就是匿名内部类
        //匿名内部类默认继承抽象类重写抽象方法并且创建匿名内部类对象
        //当类可以被继承时/接口可以被实现,就可以拥有匿名内部类形式
        C c=new C(){
            @Override
            public void m(){
            }
        };

        //普通类也具有匿名内部类形式
        B b=new B(){};
        //接口也具有匿名内部类形式
        A a=new A(){};

        //调用方法传入接口实现类对象
        //匿名内部类对象传入即可
        //当做参数使用
        //匿名内部类使用方便但是只能使用一次
        m(newA(){});

        //创建抽象类子类对象
        Dd=newD();
    }
    //参数类型是接口只能传入接口的实现类对象
    public static void m(A a){}
}

interface A{}
class B{}

abstract class C{
	public abstract void m();
}

class D extends C{
    @Override
    public void m(){}
}

2. 在接口中定义类

  • 接口里定义类,内部类接口都是默认被static修饰
public class InnerDemo4{

    public static void main(String[] args){
        System.out.println(Outer4.Inner4.i);
        System.out.println(Outer4.Inner5.j);
        System.out.println(Outer4.Inner4.Inner6.k);
    }
}

interface Outer4{
    //内部接口默认被static修饰
    static interface Inner5{
    	intj=2;
    }
    //内部类默认被static修饰
    static class Inner4{
        static int i=1;

            //内部接口默认被static修饰
        static interface Inner6{
        	int k=10;
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值