Java基础笔记(七)【面向对象——三大特性、内部类】

面向对象的三大特性

封装

  1. 封装:
    在这里插入图片描述
    私有的属性要用get、set方法来使用(快捷键:alt+insert
    还可以对于一些不合法的情况进行处理 。

    public class Student {
        //属性私有
        private String name;//名字
        private int id;//学号
        private char sex;//性别
        private int age;//年龄
    
        //生成get、set方法
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            //不合法处理
            if (age>120||age<0){
                this.age = 3;
            }else {
                this.age = age;
            }
        }
    }
    
    public class Demo05 {
        public static void main(String[] args) {
            Student student = new Student();
            student.setAge(999);//不合法
            System.out.println(student.getAge());
        }
    }
    
    //输出
    3
    
    • 封装的好处:
      1. 提高程序的安全性,保护数据。
      2. 隐藏代码的实现细节。
      3. 统一接口
      4. 系统可维护性增加了
    • 回顾下方法的重载:判断两个方法是否是同一个
      • 方法名相同
      • 传参相同

继承

  1. 继承
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NjUkW9FO-1686291063289)(Java笔记.assets/image-20230608105846328.png)]

    • 子类可以继承父类的所有方法

    • public修饰的属性可以继承 ,private修饰的属性不能继承

    • 四种修饰符:

      • public
      • protected
      • default
      • private
    • 查看继承树关系:

      • 选中该类后按快捷键ctrl+H [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CA1U7QIn-1686291063290)(Java笔记.assets/image-20230608112100919.png)]
    • 在Java中所有的类都默认直接或间接继承object类

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NS5C5UNd-1686291063290)(Java笔记.assets/image-20230608112414717.png)]

  2. super:调用父类的构造方法
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l2dzWqai-1686291063296)(Java笔记.assets/image-20230608113140909.png)]

    //启动类
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.test("wyf");
        }
    }
    
    //student派生类
    public class Student extends Person {
        private String name = "whl";
        public void test(String name){
            System.out.println(name);//wyf
            System.out.println(this.name);//whl
            System.out.println(super.name);//human
        }
    }
    
    //person父类
    public class Person /* extends Object */{
        protected String name = "human";
    }
    
    • 私有的东西无法被继承!

    • new一个student的时候,默认先调用了person的无参构造。

    • super的东西,必须放在代码的第一行;即,调用父类的构造器,必须放在子类构造器的第一行。

    • super默认调用的是无参构造。

    super注意点

    1. super调用父类的构造方法,必须在构造方法的第一个
    2. super必须只能出现在子类的方法或者构造方法中
    3. super和this不能同时调用构造方法

    super vs this:

    1. 代表的对象不同:
      • this:本身调用者这个对象
      • super:父类对象的引用
    2. 前提:
      • this:没有继承也可以使用
      • super:只能在继承条件下使用
    3. 构造方法:
      • this():本类的构造
      • super():父类的构造
    //启动类
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
    
        }
    }
    
    //student类
    public class Student extends Person {
        private String name = "whl";
    
        public Student(){
            //super();//隐式的,可以不写
            System.out.println("student无参被执行了");
        }
    }
    
    //person类
    public class Person /* extends Object */{
        protected String name = "human";
        public Person(){
            System.out.println("person无参被执行了");
        }
    }
    
    //输出
    person无参被执行了
    student无参被执行了
    
  3. 方法重写

    • 都是方法的重写,与属性无关。

      例1:static静态方法

      ​ 方法的调用只和左边的类型有关系

      //启动类
      public class Application {
          public static void main(String[] args) {
              //方法的调用,只和左边的类型有关
              A a = new A();
              a.test();//A的静态方法
      
              //父类的引用指向了子类
              B b = new A();
              b.test();//B的静态方法
          }
      }
      
      public class B {
          public static void test(){
              System.out.println("B");
          }
      }
      
      public class A extends B {
          public static void test(){
              System.out.println("A");
          }
      }
      
      //输出
      A
      B
      
    • 静态的方法和非静态的方法,不一样。

      例2:非静态方法

      ​ 子类重写了父类的方法,方法只和非静态有关

      public class Application {
          public static void main(String[] args) {
              A a = new A();
              a.test();
      
              B b = new A();
              b.test();
          }
      }
      
      public class B {
          public void test(){
              System.out.println("B");
          }
      }
      
      public class A extends B {
          public void test(){
              System.out.println("A");
          }
      }
      
      //输出
      A
      A
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hxLFHxAb-1686291063297)(Java笔记.assets/image-20230608155215920.png)]

    • 子类继承了父类,才能重写。

    重写快捷键:alt+insert

    public class A extends B {
    //    public void test(){
    //        System.out.println("A");
    //    }
    
        @Override
        public void test() {
            super.test();
        }
    }
    
    • 注意点:

      • 重写:

        • 需要有继承关系,子类重写父类的方法。

        • 方法名必须相同。

        • 参数列表必须相同。

        • 修饰符,范围可以扩大但不能缩小;public > protected > default > private

        • 抛出的异常,范围可以被缩小,但不能扩大。

        • 子类的方法名和父类一致,但方法体不同。

        • 快捷键:alt + insert override

      • 为什么需要重写:

        • 父类的功能,子类不一定需要,或者不一定满足。

多态

  1. 多态

    即,同一方法可以根据发送对象的不同而采用多种不同的行为方式。使得程序更灵活。

    • 实现动态编译;

    • 一个对象的实际类型是确定的,但可以指向的引用类型不确定了

    • 子类重写了父类的方法,就执行子类的方法。没有重写父类,就调用子类的。

      //启动类
      public class Application {
          public static void main(String[] args) {
              Student s1 = new Student();
              Person s2 = new Student();//父类的引用指向子类;都是学生,但是表现出多种状态
              Object s3 = new Student();
      
              s1.run();
              s2.run();
          }
      }
      
      //派生类
      public class Student extends Person {
          @Override
          public void run() {
              System.out.println("son run");
          }
      }
      
      //父类
      public class Person /* extends Object */{
          public void run(){
              System.out.println("person run");
          }
      }
      
      //输出
      son run
      son run
      
    • 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大

      //启动类
      public class Application {
          public static void main(String[] args) {
              Student s1 = new Student();
              Person s2 = new Student();//父类的引用指向子类;都是学生,但是表现出多种状态
              Object s3 = new Student();
      
              s1.run();
              s2.run();
      
              s1.eat();
              ((Student) s2).eat();//这里将s2强制转化成student类型
          }
      }
      
      //派生类
      public class Student extends Person {
          @Override
          public void run() {
              System.out.println("son run");
          }
      
          public void eat(){
              System.out.println("son eat");
          }
      }
      
      //父类
      public class Person /* extends Object */{
          public void run(){
              System.out.println("person run");
          }
      }
      
    • 注意:

      • 多态是方法的多态,属性没有多态。

      • 父类和子类之间的转换是有联系的,不能瞎转换,会出现类转换异常(ClassCastException)。

      • 子类能调用的方法都是自己的,或者继承父类的

      • 父类,可以指向子类,但是不能调用子类独有的方法

      • 多态存在的条件

        • 继承关系
        • 方法需要重写
        • 父类引用指向子类对象;即,Father f = new Son();
      • 有些方法不能重写

        • static方法:属于类,不属于任何实例
        • final修饰的:在常量池中,被final修饰的类没有子类
        • private修饰的:私有的,不能重写
  2. instanceof

    关键词,判断一个对象是什么类型。

    System.out.println(X instanceof Y); 编译能否通过,取决于是否存在父子关系。

    public class Application {
        public static void main(String[] args) {
            Object o = new Student();
            //Object > Person > Student
            //Object > Person > Teacher
            //Object > String
            System.out.println(o instanceof Student);
            System.out.println(o instanceof Person);
            System.out.println(o instanceof Object);
            System.out.println(o instanceof Teacher);
            System.out.println(o instanceof String);
        }
    }
    
    true
    true
    true
    false
    false
    
  3. 类型转换

    • 把子类转换为父类,向上转型;
    • 把父类转换为子类,向下转型;强制转换
  4. static关键字

    • 匿名代码块,程序在执行时并不能主动调用匿名代码块,创建对象时自动创建,在构造器之前

    • static静态代码块,类加载时直接执行,只执行一次

      public class Person {
          {
              System.out.println("匿名代码块");
          }
      
          static {
              System.out.println("静态代码块");
          }
      
          public Person() {
              System.out.println("构造器");
          }
      
          public static void main(String[] args) {
              Person person = new Person();
              System.out.println("========================");
              Person person2 = new Person();
              
          }
      }
      
      //输出
      静态代码块
      匿名代码块
      构造器
      ========================
      匿名代码块
      构造器
      
    • 静态导入包

      比如Math.random()方法,不想写太长,可以这么写:

      package com.oop.demo11;
      
      import static java.lang.Math.random;
      
      public class Test {
          public static void main(String[] args) {
              System.out.println(random());
          }
      }
      
  5. 抽象类

    • class前加了abstract就是抽象类

    • 抽象方法,只有方法名,没有具体的方法实现。

    • 抽象类的所有方法,继承了它的子类,都必须要实现它的方法。

    • 抽象类不能new,只能靠子类去实现它。

    • 抽象类中可以写普通方法。

    • 抽象方法必须在抽象类中。

    • 思考:

      • 抽象类存在构造器吗?存在
      • 抽象类存在的意义?将共有属性抽象出来,再去处理具体方法;提高开发效率,可扩展性更高。
    //抽象类
    public abstract class Demo12 {
        public abstract void doSomething();
    
        public Demo12() {
        }
    }
    
    //子类继承并实现
    public class Action extends Demo12 {
    
        @Override
        public void doSomething() {
    
        }
    }
    

接口

  1. 接口

    • 关键字interface

    • Java的类是单继承,但是Java的接口可以多继承

    • 比较接口、普通类、抽象类

      • 普通类:只有具体实现。
      • 抽象类:具体实现和规范(抽象方法)都有。
      • 接口:只有规范,自己无法写方法。约束和实现分离。

      三者图标:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWRLQlyZ-1686291063297)(Java笔记.assets/image-20230608192158643.png)]

    • 接口的本质是契约。

    • 面向对象的精髓是接口。

    • 接口中的所有定义都是抽象的。

    • 接口都需要有实现类。类通过implements实现接口。而实现了接口的类,必须要重写接口中的方法。

      //接口1
      public interface UserService {
          void add(String name);
          void delete(String name);
          void update(String name);
          void search(String name);
      }
      
      //接口2
      public interface TimService {
          void timer();
      }
      
      //接口实现类
      public class UserServiceImpl implements UserService, TimService{
      
          @Override
          public void add(String name) {
      
          }
      
          @Override
          public void delete(String name) {
      
          }
      
          @Override
          public void update(String name) {
      
          }
      
          @Override
          public void search(String name) {
      
          }
      
          @Override
          public void timer() {
      
          }
      }
      

      总结

      1. 接口是一种约束。

      2. 定义一些方法,让不同的人去实现。

      3. 接口中的方法都是public abstract

      4. 接口中的常量都是public static final

      5. 接口不能被实例化,因为没有构造方法。

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2MD9o9J7-1686291063298)(Java笔记.assets/image-20230608193636880.png)]

      6. 接口可以实现多个,通过implements关键字实现,实现类必须要重写接口中的所有方法。

内部类

  1. 内部类

    就是在一个类的内部再定义一个类,比如:A类中定义一个B类,那么B类相对于A类来说就称为内部类,而A类相对于B类来说就是外部类。

    • 分类:
      • 成员内部类
      • 静态内部类
      • 局部内部类
      • 匿名内部类
    • 内部类可以访问外部的私有属性。

    例1:成员内部类

    public class Outer {
        private int number = 10;
        public void outer(){
            System.out.println("外部类的方法");
        }
    
        class Inner{
            public void getNumber(){
                System.out.println("number = "+number);
            }
        }
    }
    
    public class Application {
        public static void main(String[] args) {
            Outer outer = new Outer();
            Outer.Inner inner = outer.new Inner();
            inner.getNumber();
        }
    }
    

    注意:内部类中访问私有属性的方法如果加static关键字,那么私有属性处也需要加static

    例2:静态内部类(无法直接访问非静态的属性)

    public class Outer {
        private static int number = 10;
        public void outer(){
            System.out.println("外部类的方法");
        }
    
        static class Inner{
            public static void getNumber(){
                System.out.println("number = "+number);
            }
        }
    }
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GFIzXqFB-1686291063298)(Java笔记.assets/image-20230608200557857.png)]

    • 一个java文件中只能有一个public class,但是可以有多个class

    例3:匿名内部类

    public class OuterTwo {
        public static void main(String[] args) {
    
        }
    }
    class A{//匿名内部类
        public static void main(String[] args) {
    
        }
    }
    
    public class OuterTwo {
        public static void main(String[] args) {
            new A().eat();//匿名对象,不用将实例保存到变量中
        }
    }
    class A{
        public void eat(){
            System.out.println("eat");
        }
    }
    

    甚至还可以new一个内部接口

    public class OuterTwo {
        public static void main(String[] args) {
            CustomerService customerService = new CustomerService() {
                @Override
                public void hello() {
                    
                }
            };
        }
    }
    interface CustomerService{
        void hello();
    }
    

    例4:局部内部类

    public class OuterThree {
        public void run(){
            class Inner{//局部内部类
                public void in(){
    
                }
            }
        }
    }
    

    另外,内部类不推荐写,但是要了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值