ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

面向对象-中级篇

2022-09-07 11:35:19  阅读:181  来源: 互联网

标签:中级 String 子类 class 面向对象 父类 public name


包:

  • 什么是包?   可以把它理解为一个文件夹
  • 包的作用?   区分相同名称的类,方便管理类,控制访问范围
  • 如何创建包?和创建文件夹一样
  • 如何引入包?语法:import 包 , 如:import java.util.*
  • 如果有两个一样的类名,就可以提供地址来区分是哪个包下的

  • 包的命名规范:

    • 只能包含数字,字母,下划线,小圆点
    • 不能以数字开头,不能用关键字,保留字
    • 正规格式:com.公司名.项目名.业务名
      • com.TX.crud.user    
  • 常用的包

    • java.lane.*  是java的基础包,默认导入不需要引入
    • java.util.*    java提供的工具包
    • java.net.*   网络开发包
    • java.awt.*  java页面开发包  
  • 细节:

    • package(打包) - 作用:生明当前类是属于哪个包
    • import(导入) - 作用:导入包

访问修饰符:  

  • 什么是访问修饰符? 用于控制方法和属性的访问权限
  • 访问修饰符分为:4种访问修饰
    • public - 公共的
    • protected - 受保护的
    • private - 私有的
    • 默认的 - 就是什么都不写
  •  细节:

    • 修饰符,可以修饰属性和方法以及类
    • 只有默认和public才能修饰类
    • 属性和成员属性的访问完成一样 
  • //细节2:只有默认和public才能修饰类
    public class Sds {
        public int i = 1; //公共
        protected int n = 2;//受保护的
        int o = 3;//默认的
        private int p = 4;//私有的
        public void show(){ //方法和属性的访问修饰符是一样的
            System.out.println("我是方法show");
        }
    }
    //细节2:只有默认和public才能修饰类
    class King{
    
    }

封装:

  • 什么是封装? 将类在的某些信息隐藏在类的内部,不允许外部直接访问,而是通过类提供的方法来对隐藏的数据进行访问和操作

  • 封装的好处? 1.只能规定的方法访问和操作数据 ,2.可以对数据进行验证,保证安全合理,3.隐藏实现细节 

  • 封装的实现步骤:

    • 将属性私有化private

    • 提供一个setXxx(参数列表)方法,对属性进行判断和赋值

    • 提供一个getXxx()方法,获取属性值

  • public class Test{
        private String name;
        private String sex = "男";
        private int age = 18;
    
        //获取属性值
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            //进行判断和赋值
            if(name.length() > 1 && name.length() < 5){
                this.name = name;
            }else {
                System.out.println("你名称太长了");
            }
    
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    }
    
    main{
        Test.setName("jack,彭于晏,吴彦祖");//肯定是错的,因为条件判断最大是5
    }
  • 构造器和Set()方法结合:

    • 如果使用构造器来给属性赋值,那么Set方法的判断就会失效,直接在构造器中调用Set方法就可以经解决

  • public Sds2(String name, String sex, int age) {
            //像使用构造器,就可以直接跳过Set()的判断了
    //        this.name = name;
    //        this.sex = sex;
            //调用本类的方法就好set方法就好了
            setName(name);
            setSex(sex);
            
        }

继承:

  • 什么是继承? 符合is a条件的类可以通过继承来解决代码的复用,如动物类和小狗类,那么小狗就可以继承动物类,因为狗有动物的行为
  • 为什么需要继承?减少代码的复用
  • 继承示意图:

  • 继承的基本语法:

    • class 子类 extends 父类{
        //继承父类,知道要有父类的属性和方法 
      }
  • 细节:

    • 子类继承了父类,非私有的属性和方法可以直接在子类访问,但私有属性不能直接访问(需要通过父类的公共方法来访问)

    • 子类必须调用父类的构造器,完成父类的初始化(理解:当去继承父类如果没调用构造器初始化父类,那么继承的是什么?)        

      • (简单理解:父亲都没有,哪来的你?) 
    • 创建子类对象,不管使用子类哪个构造器,默认会去调用父类的无参构造器,如果父类没有无参构造器,则需要在子类使用super来指定父类构造器,完成父类初始化
    • 指定父类构造器方法:super(参数列表)
    • super()使用时必须放在构造器第一行(super()只能在构造器中使用),因此super和this都是需要放在第一行的,所以不能同时在一个构造器使用
    • java所有类都是Object类的子类,所以父类可以一直追溯到Object
    • java是单继承机制,只能继承一个父类
    • 父类和子类必须满足is-逻辑,如你是飞机类去继承汽车类,这不就扯蛋了
    • public static void main(String[] args) {
            B b= new B();
      }
      
      class A{
          A(){
              System.out.println("我是A的无参构造器");
          }
          A(String mame) {
              System.out.println("我是A的有参构造器");
          }
      }
      class B extends A{//只能继承一个父类
          B(){
              //super();默认调用父类的无参构造器
              //super("jack");指定父类的构造器
              System.out.println("我是b的无参构造器");
          }
      }
  • 继承的本质:

    • 本质:先去加载父类,在加载子类
    • 问题:为什么创建的CarSon指向的堆中有父类的属性?
      • 细节中说到:因为继承了父类就会获取子类中非私有的属性和方法
    •          

Super关键字:

  • 什么是Super关键字? 可以用于直接访问父类的构造器、方法、属性

  • 理解:本类不访问直接访问父类
  • class Car{
        String name = "汽车";
        String affect = "出行";
    
    }
    class CarSon extends Car{
        String name = "跑车";
        String CarName = "Lamborghini";
    
        public void jk(){
            System.out.println("CarSon类jk方法");
        }
        public void show(){
            System.out.println(affect);//如果没指定调用的是父类的还是子类的,就从子类开始向上找
            System.out.println(name);//输出跑车,这个也等价于this.name
            System.out.println(super.name);//输出汽车
    
        }
    }
  •  细节:

    • 如不使用super,就从本类向父类查找成员,如果有重名就遵循就近原则,本类没有才找父类 

    • 找成员naem,如子类没有找父类,父类没有在找爷爷类。A->B->C,当然遵守访问权限原则

 

方法的重写/覆盖:

  • 什么是方法的重写? 就是子类的某个方法和父类的某个方法,方法名称、返回类型、参数列表一样

  • 细节:

    • 子类的形参列表,方法名称,要和父类形参列表,方法名称完全一样

    • 子类的返回类型要和父类一致,或保持父子关系,如父类是Object返回类型,子类是String返回类型

    • 子类不能缩小方法的访问权限但是可以放大 public > protected > 默认 > private

    • class Car{
          public void show(){
              System.out.println("我是show方法");
          }
          public Object show2(){
              return 1.1;
          }
          private void show3(){
              System.out.println("我是show3方法");
          }
      
      }
      class CarSon extends Car{
          //子类的形参列表,方法名称,要和父类形参列表,方法名称完全一样
          public void show(){
              System.out.println("我是子类,我重写了show方法");
          }
          //子类的返回类型要和父类一致,或保持父子关系,如父类是Object子类是String
          public String show2(){
              return "1.1";
          }
          //子类不能缩小方法的访问权限但是可以放大 public > protected > 默认 > private
          public void show3(){
              System.out.println("我是子类,我重写了show3方法");
          }
      
      }

多态:

  • 什么是多态? 多种形态,多态是建立在继承和封装的基层上
    • 理解:完成某个行为的时候,不同的对象去完成会产生不同的状态 
    • 例子:方法的重写和重载就是多态的一种体现  -> 方法的多态
      • 如父类引用=子类对象( 如:Animal animal = new Dog() ) - > 对象的多态
  • 对象的多态:

    • Animal animal = new Animal( )  - ->  左边是编译类型  - 右边是运行类型 
    • 一个对象的编译类型和运行类型可以不一致,当然只两者要保持继承关系
    • 编译类型在确定对象后是不能改变的,运行类型可以改变
      • 下面案例中就使用对象的多态完成了动物的喂食问题
      • 小狗有父类,食物有父类,通过小狗和食物的父类编译类型去引用它的子类对象完成操作  
    • public class Test {
          public static void main(String[] args) {
              person person = new person("汤姆");
              Dog2 dog2 = new Dog2("小白");
              Bone2 bone2 = new Bone2("骨头");
              person.show4(dog2,bone2);
              //解决:用到多态对象就完美的解决该问题喂食方法的重复问题
              Cat2 cat2 = new Cat2("小花");
              Bone2 bone3 = new Bone2("骨头");
              person.show5(cat2,bone3);
              
          }
      }
      
      //目的:让人去给动物喂食物
      class Animal2{
          private String name;
          public Animal2(String name) {
              this.name = name;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
      }
      class Fish2{
          private String name;
          public Fish2(String name) {
              this.name = name;
          }
          public String getName() {
              return name;
          }
          public void setName(String name) {
              this.name = name;
          }
      }
      
      class Dog2 extends Animal2{
          public Dog2(String name) {
              super(name);
          }
      }
      class Cat2 extends Animal2{
          public Cat2(String name) {
              super(name);
          }
      }
      
      class Bone2 extends Fish2{
          public Bone2(String name) {
              super(name);
          }
      }
      
      class person{
          public person(String name) {
              this.name = name;
          }
          private String name;//主人名称
          //问题:如果我有一百种小动物,那我的喂食方法也需要写一百个吗
          public void show4(Dog2 dog2,Bone2 bone2){ //喂食方法
              System.out.println("主人"+name+"给"+dog2.getName()+"吃"+bone2.getName());
          }
          //解决:用到多态对象就完美的解决该问题
          public void show5(Animal2 animal2,Fish2 fish2){ //喂食方法
              System.out.println("主人"+name+"给"+animal2.getName()+"吃"+fish2.getName());
          }
      
      }
  • 多态向上转型:

    • 什么是向上转型? 子类是运行类型,父类是编译类型
    • 细节:
      • 不能调用本身的特有成员,可以调用父类的所有成员(遵守访问权限)
        • 为什么不能调用本身特有成员? 因为在编译阶段,能调用哪些成员,是由编译类型决定(说白了就是加载编译类型的成员变量)
      • 因为最终的的运行看子类的具体表现
        • 因为最终的的运行看子类的具体表现什么意思? - 调用成员时还是按子类向父类的向上查找
    • public class Test {
          public static void main(String[] args) {
              //普通继承 - 可以调用本身特有的成员,和父类中所有的成员(遵守访问权限)
              Dog2 dog2 = new Dog2();
              dog2.eat();//吃骨头
              dog2.action();
              dog2.show();
              //多态向上转型 - 不能调用本身的特有成员,可以调用父类的所有成员(遵守访问权限)
                  //为什么不能调用本身特有成员? 因为在编译阶段,能调用哪些成员,是由编译类型决定(说白了就是加载编译类型的成员变量)
                      //Animal2是编译类型,Dog2是运行类型
                  //为什么animal2.eat();输出吃骨头不是吃东西? - 因为最终的的运行看子类的具体表现
                      //因为最终的的运行看子类的具体表现什么意思? - 调用成员时还是按子类向父类的向上查找
              Animal2 animal2 = new Dog2();
              animal2.eat();//吃骨头
          }
      }
      class Animal2{
          public void eat(){
              System.out.println("吃东西");
          }
          public void action(){
              System.out.println("撒娇");
          }
      }
      class Dog2 extends Animal2{
          public void eat(){
              System.out.println("吃骨头");
          }
          public void show(){
              System.out.println("展示才艺");
          }
      }
        
  • 多态向下转型:

    • 什么是向下转型? 把父类的的引用强转,为编译类型是子类的对象( 如:Dog dog = (Dog)animal )

    • 细节:

      • 只能强转父类的引用,终于不是父类的对象

      • 强转的父类引用必须是和当前对象有关联的

      • 向下转型后,可以调用子类中所有的成员

    • Animal2 animal2 = new Dog2();
      animal2.eat();//吃骨头
      
      //多态的向下转型 - 强转需要保持关联性
      //当初是Dog2向上转型为父类的animal2,那么向下转型也要保持这个关系
      Dog2 dog3 = (Dog2) animal2;
       og3.show();
  • 属性没有重写之说:

    • 属性的值看编译类型 -  
    • public class Test {
          public static void main(String[] args) {
              A a = new B();
              System.out.println(a.name);//MIUI
              B b = new B();
              System.out.println(b.name);//Huawei
          }
      }
      class A{
          public String name = "MIUI";
      }
      class B extends A{
          public String name = "Huawei";
      }
  • instanceOf比较操作符:

    • 用与判断对象的运行类型是否为XX类型或XX类型的子类型  

    • public class Test {
          public static void main(String[] args) {
              A a = new A();
              System.out.println(a instanceof A);//真
              A a2 = new B();
              B b = new B();
              System.out.println(b instanceof A);//真
          }
      }
      class A{
          public String name = "MIUI";
      }
      
      class B extends A{
          public String name = "Huawei";
      }
  • java的动态绑定机制(重点):

    • 什么是动态绑定机制?
      • 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
      • 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用
  • public class Test {
        public static void main(String[] args) {
            A a = new B();
            //没有把B类中的sum()方法注销时的输出结果
            System.out.println(a.sum());//220
            System.out.println(a.sum1());//210
    
            //把B类中的sum()方法注销后输出的结果
             //为什么是210? 因为地态绑定机制的原因,调用到getl()时就回到运行类型的调用,没有该方法在往上寻找
            System.out.println(a.sum());//210
            System.out.println(a.sum1());//210
    
        }
    }
    class A{
        public int a = 100;
    
        public int sum(){
            return getl() + 10;
        }
        public int sum1(){
            return a + 10;
        }
        public int getl(){
            return a;
        }
    }
    class B extends A{
        public int a = 200;
    //    public int sum(){
    //        return a + 20;
    //    }
        public int sum1(){
            return a + 10;
        }
        public int getl(){
            return a;
        }
    }
  • 多态数组:

    • 什么是多态数组? 在一个数组中可以存放不同的子类
    • 案例:
  • public class Test {
        public static void main(String[] args) {
            Person[] person = new Person[5];
            person[0] = new Student("小白",18,"学生");
            person[1] = new Teacher("老王",32,"老师");
            for (int i = 0; i < person.length; i++) {
                //show方法是重写的 - 但运行结果是根据运行类型
                if(person[i] != null){
                    String show = person[i].show();
                    System.out.println(show);
                    //向下转型,调用特有的成员
                    if(person[i] instanceof Student){
                        System.out.println(((Student)person[i]).study());
                    }
                    if(person[i] instanceof Teacher){
                        System.out.println(((Teacher)person[i]).teach());
                    }
                }
            }
        }
    }
    class Person{
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        private String name;
        private int age;
    
        public String show(){
            return name+"-"+age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    class Student extends Person{
        public Student(String name, int age, String job) {
            super(name, age);
            this.job = job;
        }
    
        private String job;
        public String show(){
            return super.show()+"-"+job;
        }
        public String study(){
            return super.getName()+"在收听java";
        }
    
    }
    class Teacher extends Person{
        public Teacher(String name, int age, String job) {
            super(name, age);
            this.job = job;
        }
        private String job;
        public String show(){
            return super.show()+"-"+job;
        }
        public String teach(){
            return super.getName()+"给学生将java";
        }
    }

Object顶级父类下的常见方法:

  • equals方法:

    • equlas:是Object类中的方法,默认(没被重写时)是判断引用类型的地址是否相等,子类往往重写该方法用与判断内容是否相等(如String和Integer)

    • 一般 equals 和 == 会进行一个比较(面试):

      • == :是一个比较运算符

      • == :即可以判断该基本数据类型,又可以判引用类型

      • ==:判断基本数据类型判断该的值,判断的是引用类型判断该的是地址  

    • 重写equals方法:

    • public class Test {
          public static void main(String[] args) {
              Person person1 = new Person("小白",18,'男');
              Person person = new Person("小白",18,'男');
      //        System.out.println(person1.equals(person));//false(没有重写equals默认比较地址)
              System.out.println(person1.equals(person));//true(重写equals后)
          }
      }
      class Person{
          public Person(String name, int age, char sex) {
              this.name = name;
              this.age = age;
              this.sex = sex;
          }
          String name;
          int age;
          char sex;
          public boolean equals(Object obj) {
              //this代表的就是obj(自己调用我自己)
              if(this == obj){
                  return true;
              }
              if(obj instanceof Person){
                  Person p = (Person)obj;
                  return this.name == p.name && this.age == p.age && this.sex == p.sex;
              }
              return false;
          }
      }
  • hashCode方法: 

    • hashCode返回的是哈希码值,支持该方法是为了提高哈希表   
    • 哈希值主要根据地址类(但哈希值不完全等价于地址,因为Object的hashCode方法会根据不同的对象返回不同的整数) 
    • 两给引用,指向的是同一个对象,则哈希值肯定是一样,反知
    • public class Test {
          public static void main(String[] args) {
              Person person1 = new Person("小白");
              Person person2 = new Person("小红");
              System.out.println(person1.hashCode());//356573597
              System.out.println(person2.hashCode());//1735600054
          }
      }
      class Person{
          public Person(String name) {
              this.name = name;
          }
          String name;
  • toString方法: 
    • 默认返回:全类名+@+哈希值的十六进制
    • 一般子类重写用来返回对象的属性信息,打印对象或拼接对象时,都会该方法会自动调用
    • public class Test {
          public static void main(String[] args) {
              Person person1 = new Person("小白","打游戏");
      //        System.out.println(person1.toString());//默认输出
              System.out.println(person1);//重写输出:Person{name='小白', hobby='打游戏'}
          }
      }
      class Person{
          public Person(String name, String hobby) {
              this.name = name;
              this.hobby = hobby;
          }
          String name;
          String hobby;
      
          @Override
          public String toString() {
              return "Person{" +
                      "name='" + name + '\'' +
                      ", hobby='" + hobby + '\'' +
                      '}';
          }
      }
  • finalize方法:

    • finalize方法是做什么的? 当对象被回收时,系统自动调用该方法(注意不是该方法用来回收对象,而是在被回收前做一些操作) 

    • 什么时候被回收?当对象没有引用指向它时,jvm认为该对象就是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁前会调用finalize方法

    • 垃圾回收机制?是由GC算法来决定(也就是说对象没引用的时候就马上销毁,而是由GC算法决定的),但是可以通过System.gc();来主动触发垃圾回收机制

    • public class Test {
          public static void main(String[] args) {
              BaoMa baoMa = new BaoMa("宝马");
              baoMa = null;
              System.gc();//主动调用垃圾回收机制
              System.out.println("程序退出");
          }
      }
      class BaoMa{
          public BaoMa(String name) {
              this.name = name;
          }
          String name;
      
          @Override
          protected void finalize() throws Throwable {
              System.out.println("销毁汽车"+name);
              System.out.println("释放资源");
          }
      }

 

 断点调试:

  • 什么是断点调试? 通过一行一行的去执行代码,查看代码的执行

  • 类加载的断点调试演示:       
  •  

 

     

     

        

                    

 

   

 

  

  

 

        

   

 

 

 

      

 

 

     

 

   

标签:中级,String,子类,class,面向对象,父类,public,name
来源: https://www.cnblogs.com/Mr-shne/p/16533055.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有