面向对象 下 (笔记十三)

本文深入讲解Java中的关键概念,包括static关键字的使用方法、main方法的语法、代码块的作用、final关键字的功能、抽象类与抽象方法的区别、多态的应用、接口的使用方法及其与抽象类的对比、内部类的特点等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在这里插入图片描述
多态是编译时行为还是运行时行为?
答:运行时行为

一、关键字:static

在这里插入图片描述

/**
 * @Description: $static 关键字的使用
 * 1、static:静态的
 * 2、static可以用来修饰:属性、方法、代码块、内部类
 *
 * 3、使用static修饰属性:静态变量
 *         3.1、 属性:按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
 *          实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象的非静态属性时,不会导致其他对象中同样的属性值的修改。
 *          静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
 *        3.2、static修饰属性的其他说明
 *         ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
 *         ② 静态变量的加载要早于对象的创建。
 *         ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份
 *
 * 4、使用static修饰方法:静态方法
 *     ① 随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
 *     ②           静态方法      非静态方法
 *          类       yes           no
 *          对象      yes           yes
 *     ③ 静态方法中,只能调用静态的方法或属性
 *        非静态的方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
 * 5、static注意点:
 *  在静态的方法内,不能使用this关键字,super关键字
 *
 * @Author: dyq
 * @Date: $
 */
public class StaticTest {
    public static void main(String[] args) {
        Chinese.nation ="中国";

        Chinese c1 = new Chinese();
          c1.name="赵丽颖";
          c1.age=33;
          c1.nation="CHN";

        Chinese c2 = new Chinese();
        c2.name="杨幂";
        c2.age=30;
        c2.nation="CHINA";
        System.out.println(c1.nation); //CHINA

        c1.eat();
        Chinese.show(); //我爱中国,我是中国人。
     //   Chinese.eat();//编译不通过
       // Chinese.info(); 没指明调用那个
        
    }
}
 //中国人
 class   Chinese{
    String name;
    int age;
    static String nation;

    public   void  eat(){
        System.out.println("中国人吃中餐。");
        //调用非静态结构
        this.info();
        System.out.println("name:"+name);
        //调用静态结构
        walk();
        System.out.println("nation:"+Chinese.nation);
        
    }

     public static   void  show(){
         System.out.println("我爱中国,我是中国人。");
         //eat();
         //name="Tom"
         //可以调用静态的结构
         System.out.println(Chinese.nation);
         walk();
     }

     public  void  info(){
         System.out.println("name:"+name+",age:"+age);
     }
     public static  void walk(){
     }
}

二、 理解main方法的语法

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

/**
 * @Description: Main方法的使用和说明
 *  1.main()方法是程序的入口
 *  2.main()方法也是一个普通的静态方法
 *  3.main()方法可以作为我们与控制台交互的方式。(之前:使用Scanner)
 * 静态调静态就不要new对象,静态调非静态那必须new对象来调用$
 * @Author: dyq
 * @Date: $
 */
public class MainTest {
    public static void main(String[] args) {//入口
        Main.main(new String[3]);

        MainTest mainTest = new MainTest();
        mainTest.show();
    }
    public  void  show(){

    }
}
args_0
args_1
args_2

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

​ 在Java中,使用 { } 括起来的代码被称为代码块

1、代码块(或初始化块)的作用:

对Java类或对象进行初始化

2.代码块的分类

局部代码块(方法中)
构造代码块(类中方法外)
静态代码块(类中方法外)
一个类中代码块若有修饰符,则只能被static修饰,称为静态代码块
(static block),没有使用static修饰的,为非静态代码块。

/**
 * @Description:  类的成员之四:代码块(或初始化)
 *
 * 静态代码块:
 * 》内部可以有输出语句
 * 》随着类的加载而执行
 *
 * 非静态代码块:
 *  》内部可以有输出语句
 *  》随着对象的创建而执行
 *
 *
 * $
 * @Author: dyq
 * @Date: $
 */
public class BlockTest {
    /*
       局部代码块
           位置:方法中定义
           作用:限定变量的生命周期,及早释放,提高内存利用率
    */
    public static void main(String[] args) {

        String s = Person.desc;
        Person p1 = new Person();
        Person p2 = new Person();
        Person.info();
    }
}

    class Person {
        //属性
        String name;
        int age;
        static String desc = "我是一个人";

        //构造器
        public Person(String name, int age) {
            this.name = name;
            this.age = age;

        }

        public Person() {

        }

        //static的代码块 ,静态代码块
         /*
        静态代码块:
            位置:类中方法外定义
            特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
            作用:在类加载的时候做一些数据初始化的操作
     */
        static {
            System.out.println("hello,static block");
        }
        //非静态代码块
         /*
         构造代码块:
         位置:类中方法外定义
         特点:每次构造方法执行的时,都会执行该代码块中的代码,并且在构造方法执行前执行
         作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
     */
        {
            System.out.println("hello,block");
            age=10;
        }
        //方法
        public void eat() {
            System.out.println("吃饭!");
        }

        @Override
        public String toString() {
            return "Person [name=" + name + ",age=" + age + "]";
        }

        public  static  void  info(){
            System.out.println("我是静态方法!");
        }
    }
hello,static block
hello,block
hello,block
我是静态方法!

在这里插入图片描述

四、关键字:final

在Java中声明类、变量和方法时,可使用关键字final来修饰,表示“最终的”。

final标记的类不能被继承。提高安全性,提高程序的可读性。 String类、System类、StringBuffer类
final标记的方法不能被子类重写。 比如:Object类中的getClass()。
final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只能被赋值一次。
final标记的成员变量必须在声明时或在每个构造器中或代码块中显式赋值,然后才能使用。final double MY_PI = 3.14

在这里插入图片描述

/**
* @Description:关键字:Final
 * 1、final可以用来修饰的结构:类、方法、变量
 * 2、final用来修饰一个类;此类不能被其他类所继承。
 * 3、final 用来修饰方法:表明此方法不可以被重写
 * 4、final用来修饰变量;此时的“变量”就称为是一个常量
 *  4.1 final修饰属性,可以考虑赋值的位置有;显式初始化,代码块中初始化,构造器中初始化
* @Author: dyq
* @Date: 2021/3/31
*/
public class FinalTest {
    //final用来修饰变量;
    final int width =10;
    public  void dowidth(){
       // width =20;
    }
    public static void main(String[] args) {
        int num =10;
        num = num+5;
    }
}

final  class  FinalA{

}
//final用来修饰一个类;此类不能被其他类所继承
//class  B extends  FinalA{}

五、抽象类与抽象方法

随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类
在这里插入图片描述

/**
 * @Description: abstract 关键字的使用
 * 1、abstract:抽象类
 * 2、abstract可以用来修饰的结构:类,方法
 * 3、abstract修饰类:抽象类
 *               >此类不能实例化
 *               >抽象类中多一定有构造器,便于子类实例化时调用
 *               >开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
 *4、abstract修饰方法,抽象方法
 *          >抽象方法只有方法的声明,没有方法体
 *          >抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。
 *          >包含抽象方法的类,一定是一个抽象类,反之,抽象类中可以没有抽象方法
 * @Author: dyq
 * @Date: $
 */
public class AbstractTest {
    public static void main(String[] args) {
       //抽象类不能实例化
//        Person1 p1= new Person1();
//        p1.eat();
    }
}

abstract class  Person1{
    String name;
    int age;
    
    public  Person1(){
       
    }

    public Person1(String name, int age) {
        this.name = name;
        this.age = age;
    }
//    不是抽象方法
//    public void eat() {
//        System.out.println("吃饭!");
//    }

    public abstract void eat(); 
      
}

class Student extends Person1{
    public  Student(String name, int age){
        super(name, age);
    }
    //抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。
    @Override
    public void eat() {
        
    }
} 

多态的应用:模板方法设计模式(TemplateMethod)

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

六、 接口(interface)

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

**
 * @Description: 接口的使用
 * 1、接口使用interface来定义
 * 2、java中,接口和类是并列的两个结构
 * 3、如何定义接口,定义接口中的成员
 *     3.1 JDK7以前:只能定义全局常量和抽象方法
 *        》全局常量:public static final的,书写时也可以省略
 *        》抽象方法:public abstract的
 *     3.2 JDK8:除了全局常量和抽象方法之外,还可以定义静态方法,默认方法
 * 4、接口中不能定义构造器,意味着接口不可以实例化
 * 5、java开发中,接口都通过类去实现(implements)的方式来使用
 *   如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
 *   如果实现类没有覆盖接口中所有的拍象方法,则此实现类仍为一个抽象类
 *6、java类可以实现多个接口----》弥补了java单继承的局限性
 *    多个接口就用逗号隔开
 *    格式:class AA extends BB implements CC,DD,EE
 * 7、接口和接口之间可以继承,而且可以多继承  
 *    
 * @Author: dyq
 * @Date:2021年3月31日 $
 */
public class InterfaceTest {
    public static void main(String[] args) {
        System.out.println(eat.MAX_SPEED);
        System.out.println(eat.MIN_SPEED);
       // eat.MIN_SPEED=2;
       person p = new person();
       p.run();
       p.stop();

       cat c = new cat();
       c.run();
       c.stop();
       c.sleep();
    }
}

interface  eat{
    //全局常量   常量都是用大写字母来命名
    public  static  final int MAX_SPEED=36;
      int MIN_SPEED =1;  //省略了public  static  final

    //抽象方法
    public  abstract  void  run();
//    省略了public  abstract
    void stop();
}

interface  sleep{
    public  static  final int MAX_SLEEP=8;// 最长睡眠时间

    public abstract void sleep();
}

class  person implements  eat{

    @Override
    public void run() {
        System.out.println("他真厉害,跑步得第一名!");
    }

    @Override
    public void stop() {
        System.out.println("他的刹车技术牛逼!");
    }
}

class  cat implements eat,sleep{

    @Override
    public void run() {
        System.out.println("小猫跑!");
    }

    @Override
    public void stop() {
        System.out.println("小猫停下!");
    }

    @Override
    public void sleep() {
        System.out.println("小猫一天最多睡:"+MAX_SLEEP+"个小时!");
    }
}

//***************************接口多继承*************************************
interface  AA {
    void method1();
}
interface BB{
    void method2();
}

interface CC extends  AA,BB{
    
}

class DD implements CC{
    @Override
    public void method1() {
        
    }

    @Override
    public void method2() {

    }
}

输出结果:

36
1
他真厉害,跑步得第一名!
他的刹车技术牛逼!
小猫跑!
小猫停下!
小猫一天最多睡:8个小时!

接口的应用:代理模式(Proxy)(了解)

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

/**
 * @Description: $
 * @Author: dyq
 * @Date: $
 */
public interface Network {
     public void browse();
}
// 被代理类
class RealServer implements Network {
    @Override
    public void browse() {
        System.out.println("真实服务器上网浏览信息");
    }
}

// 代理类
class ProxyServer implements Network {
    private Network network;
    public ProxyServer(Network network) {
        this.network = network;
    }
    public void check() {
        System.out.println("检查网络连接等操作");
    }
    public void browse() {
        check();
        network.browse();
    }
}
class ProxyDemo {
    public static void main(String[] args) {
        Network net = new ProxyServer(new RealServer());
        net.browse();
    }
}

输出:

检查网络连接等操作
真实服务器上网浏览信息

在这里插入图片描述

接口和抽象类之间的对比(面试题)

在这里插入图片描述
在开发中,常看到一个类不是去继承一个已经实现好的类,而是要么继承抽象类,
要么实现接口。

Java 8中关于接口的改进

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

public class SubClassTest {

    public static void main(String[] args) {

  SubClass s =new SubClass();

   // s.method1(); //知识点1:接口中定义的静态方法,只能通过接口来调用
    ComparA.method1();
    //知识点2:通过实现类的对象,可以调用接口中的默认方法
//  如果实现类重写了接口的方法,调用时,仍然调用的是重写以后的方法
    s.method2();
    //知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参的方法
    //那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法 =====》类优先原
    // 知识点4。如果实现类实现了多个接口,而这多个接口中定义了同亳同参数的默认方法,
    // 那么在实现类没有重写此方法的情况下,报错。-->接口冲突。
    //这就需要我们必须在实现类中重写此方法
      s.method3();
   }
}
class  SubClass extends SuperClass implements ComparA,ComparB{
    public  void  method2(){
        System.out.println("SubClass:上海");
    }
    public  void  method3(){
        System.out.println("SubClass:深圳");
    }
    //知识点5:如何在子类(或实现类的方法中调用父类,接口中被重写的方法
    public  void myMethod(){
        method3();//自己定义的重写的方法
        super.method3();//调用的是父类的方法
        ComparA.super.method3();
        ComparB.super.method3();
    }
}

七、类的内部成员之五:内部类

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

【注意】

  1. 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员 内部类中才可声明static成员。
  2. 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
  3. 成员内部类可以直接使用外部类的所有成员,包括私有的数据
  4. 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
/**
 * @Description: 类的内部成员之五。内部类
 * 1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
 * 2. 内部类的分类:成员内部类 VS 局部内部类(方法内,代码块内,构造器内)$
 * 3、成员内部类:一方面,作为外部类的成员:
 *               >调用外部类的结构
 *               》可以被static修饰
 *               》可以被4种不同的权限修饰
 *
 *  另一方面,作为一个类:
 *               》类内可以定义属性,方法,构造器等
 *               》可以被final修饰,表示此类不能被继承,言外之意,不使用final,就可以被继承
 *               》可以被abstract修饰
 * 4,关注如下3个问题
 *    4.1 如何实例化成员内部类的对象
 *    4.2 如何在成员内部类中区分调用外部类的结构
 *    4.3 开发中局部内部类的使用
 * @Author: dyq
 * @Date: $
 */
public class InnerClassTest {
    public static void main(String[] args) {
        //创建Dog实例(静态的成员内部类)
        Person.Dog dog = new Person.Dog();
        dog.show();
        //创建Bird实例(非静态的成员内部类)
        Person p = new Person();
        Person.Bird bird =p.new Bird();
        bird.sing();
        System.out.println();
        bird.display("黄鹂");
    }
}

class  Person{
    String name ="小雷";
    int age;
 public  void  eat(){
     System.out.println("人:吃饭");
 }




    //静态成员内部类
//   abstract static class Dog{
    static class Dog{
       String name ="小敏";
       int age;

       public  void show(){
           System.out.println("卡拉是条狗");
       }
    }
    //非静态成员内部类
//    final  class Bird{
     class Bird{
       String name ="青丝";
       public  Bird(){
       }

       public  void  sing(){
           System.out.println("我是一只小小鸟");
           Person.this.eat();//调用外部类的非静态属性
           eat();
       }

       public  void  display(String name){
           System.out.println(name); //方法的形参
           System.out.println(this.name);//内部类的属性
           System.out.println(Person.this.name);//外部类的属性
       }

    }


    public  void  method(){
        //局部内部类
        class AA{
        }
    }

    {
        //局部内部类
        class BB{

        }
    }
    public Person(){
        //局部内部类
        class CC{

        }
    }
}
卡拉是条狗
我是一只小小鸟
人:吃饭
人:吃饭

黄鹂
青丝
小雷

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

北街风

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

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

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

打赏作者

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

抵扣说明:

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

余额充值