面向对象-中级篇

打印 上一主题 下一主题

主题 917|帖子 917|积分 2751

包:


  • 什么是包?   可以把它理解为一个文件夹
  • 包的作用?   区分相同名称的类,方便管理类,控制访问范围
  • 如何创建包?和创建文件夹一样
  • 如何引入包?语法: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才能修饰类
    • 属性和成员属性的访问完成一样 

    1. //细节2:只有默认和public才能修饰类
    2. public class Sds {
    3.     public int i = 1; //公共
    4.     protected int n = 2;//受保护的
    5.     int o = 3;//默认的
    6.     private int p = 4;//私有的
    7.     public void show(){ //方法和属性的访问修饰符是一样的
    8.         System.out.println("我是方法show");
    9.     }
    10. }
    11. //细节2:只有默认和public才能修饰类
    12. class King{
    13. }
    复制代码
封装:


  • 什么是封装? 将类在的某些信息隐藏在类的内部,不允许外部直接访问,而是通过类提供的方法来对隐藏的数据进行访问和操作
  • 封装的好处? 1.只能规定的方法访问和操作数据 ,2.可以对数据进行验证,保证安全合理,3.隐藏实现细节 
  • 封装的实现步骤:

    • 将属性私有化private
    • 提供一个setXxx(参数列表)方法,对属性进行判断和赋值
    • 提供一个getXxx()方法,获取属性值

    1. public class Test{
    2.     private String name;
    3.     private String sex = "男";
    4.     private int age = 18;
    5.     //获取属性值
    6.     public String getName() {
    7.         return name;
    8.     }
    9.     public void setName(String name) {
    10.         //进行判断和赋值
    11.         if(name.length() > 1 && name.length() < 5){
    12.             this.name = name;
    13.         }else {
    14.             System.out.println("你名称太长了");
    15.         }
    16.     }
    17.     public String getSex() {
    18.         return sex;
    19.     }
    20.     public void setSex(String sex) {
    21.         this.sex = sex;
    22.     }
    23. }
    24. main{
    25.     Test.setName("jack,彭于晏,吴彦祖");//肯定是错的,因为条件判断最大是5
    26. }
    复制代码
  • 构造器和Set()方法结合:

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

    1. public Sds2(String name, String sex, int age) {
    2.         //像使用构造器,就可以直接跳过Set()的判断了
    3. //        this.name = name;
    4. //        this.sex = sex;
    5.         //调用本类的方法就好set方法就好了
    6.         setName(name);
    7.         setSex(sex);
    8.         
    9.     }
    复制代码
继承:


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



  • 继承的基本语法:

      1. class 子类 extends 父类{
      2.   //继承父类,知道要有父类的属性和方法
      3. }
      复制代码

  • 细节:

    • 子类继承了父类,非私有的属性和方法可以直接在子类访问,但私有属性不能直接访问(需要通过父类的公共方法来访问)
    • 子类必须调用父类的构造器,完成父类的初始化(理解:当去继承父类如果没调用构造器初始化父类,那么继承的是什么?)        

      • (简单理解:父亲都没有,哪来的你?) 

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

  • 继承的本质:

    • 本质:先去加载父类,在加载子类
    • 问题:为什么创建的CarSon指向的堆中有父类的属性?

      • 细节中说到:因为继承了父类就会获取子类中非私有的属性和方法




    •          

Super关键字:


  • 什么是Super关键字? 可以用于直接访问父类的构造器、方法、属性
  • 理解:本类不访问直接访问父类
    1. class Car{
    2.     String name = "汽车";
    3.     String affect = "出行";
    4. }
    5. class CarSon extends Car{
    6.     String name = "跑车";
    7.     String CarName = "Lamborghini";
    8.     public void jk(){
    9.         System.out.println("CarSon类jk方法");
    10.     }
    11.     public void show(){
    12.         System.out.println(affect);//如果没指定调用的是父类的还是子类的,就从子类开始向上找
    13.         System.out.println(name);//输出跑车,这个也等价于this.name
    14.         System.out.println(super.name);//输出汽车
    15.     }
    16. }
    复制代码
  •  细节:

    • 如不使用super,就从本类向父类查找成员,如果有重名就遵循就近原则,本类没有才找父类 
    • 找成员naem,如子类没有找父类,父类没有在找爷爷类。A->B->C,当然遵守访问权限原则


 
方法的重写/覆盖:


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


  • 细节:

    • 子类的形参列表,方法名称,要和父类形参列表,方法名称完全一样
    • 子类的返回类型要和父类一致,或保持父子关系,如父类是Object返回类型,子类是String返回类型
    • 子类不能缩小方法的访问权限但是可以放大 public > protected > 默认 > private
      1. class Car{
      2.     public void show(){
      3.         System.out.println("我是show方法");
      4.     }
      5.     public Object show2(){
      6.         return 1.1;
      7.     }
      8.     private void show3(){
      9.         System.out.println("我是show3方法");
      10.     }
      11. }
      12. class CarSon extends Car{
      13.     //子类的形参列表,方法名称,要和父类形参列表,方法名称完全一样
      14.     public void show(){
      15.         System.out.println("我是子类,我重写了show方法");
      16.     }
      17.     //子类的返回类型要和父类一致,或保持父子关系,如父类是Object子类是String
      18.     public String show2(){
      19.         return "1.1";
      20.     }
      21.     //子类不能缩小方法的访问权限但是可以放大 public > protected > 默认 > private
      22.     public void show3(){
      23.         System.out.println("我是子类,我重写了show3方法");
      24.     }
      25. }
      复制代码


多态:


  • 什么是多态? 多种形态,多态是建立在继承和封装的基层上

    • 理解:完成某个行为的时候,不同的对象去完成会产生不同的状态 
    • 例子:方法的重写和重载就是多态的一种体现  -> 方法的多态

      • 如父类引用=子类对象( 如:Animal animal = new Dog() ) - > 对象的多态


  • 对象的多态:

    • Animal animal = new Animal( )  - ->  左边是编译类型  - 右边是运行类型 
    • 一个对象的编译类型和运行类型可以不一致,当然只两者要保持继承关系
    • 编译类型在确定对象后是不能改变的,运行类型可以改变

      • 下面案例中就使用对象的多态完成了动物的喂食问题
      • 小狗有父类,食物有父类,通过小狗和食物的父类编译类型去引用它的子类对象完成操作  

      1. public class Test {
      2.     public static void main(String[] args) {
      3.         person person = new person("汤姆");
      4.         Dog2 dog2 = new Dog2("小白");
      5.         Bone2 bone2 = new Bone2("骨头");
      6.         person.show4(dog2,bone2);
      7.         //解决:用到多态对象就完美的解决该问题喂食方法的重复问题
      8.         Cat2 cat2 = new Cat2("小花");
      9.         Bone2 bone3 = new Bone2("骨头");
      10.         person.show5(cat2,bone3);
      11.         
      12.     }
      13. }
      14. //目的:让人去给动物喂食物
      15. class Animal2{
      16.     private String name;
      17.     public Animal2(String name) {
      18.         this.name = name;
      19.     }
      20.     public String getName() {
      21.         return name;
      22.     }
      23.     public void setName(String name) {
      24.         this.name = name;
      25.     }
      26. }
      27. class Fish2{
      28.     private String name;
      29.     public Fish2(String name) {
      30.         this.name = name;
      31.     }
      32.     public String getName() {
      33.         return name;
      34.     }
      35.     public void setName(String name) {
      36.         this.name = name;
      37.     }
      38. }
      39. class Dog2 extends Animal2{
      40.     public Dog2(String name) {
      41.         super(name);
      42.     }
      43. }
      44. class Cat2 extends Animal2{
      45.     public Cat2(String name) {
      46.         super(name);
      47.     }
      48. }
      49. class Bone2 extends Fish2{
      50.     public Bone2(String name) {
      51.         super(name);
      52.     }
      53. }
      54. class person{
      55.     public person(String name) {
      56.         this.name = name;
      57.     }
      58.     private String name;//主人名称
      59.     //问题:如果我有一百种小动物,那我的喂食方法也需要写一百个吗
      60.     public void show4(Dog2 dog2,Bone2 bone2){ //喂食方法
      61.         System.out.println("主人"+name+"给"+dog2.getName()+"吃"+bone2.getName());
      62.     }
      63.     //解决:用到多态对象就完美的解决该问题
      64.     public void show5(Animal2 animal2,Fish2 fish2){ //喂食方法
      65.         System.out.println("主人"+name+"给"+animal2.getName()+"吃"+fish2.getName());
      66.     }
      67. }
      复制代码

  • 多态向上转型:

    • 什么是向上转型? 子类是运行类型,父类是编译类型
    • 细节:

      • 不能调用本身的特有成员,可以调用父类的所有成员(遵守访问权限)

        • 为什么不能调用本身特有成员? 因为在编译阶段,能调用哪些成员,是由编译类型决定(说白了就是加载编译类型的成员变量)

      • 因为最终的的运行看子类的具体表现

        • 因为最终的的运行看子类的具体表现什么意思? - 调用成员时还是按子类向父类的向上查找


      1. public class Test {
      2.     public static void main(String[] args) {
      3.         //普通继承 - 可以调用本身特有的成员,和父类中所有的成员(遵守访问权限)
      4.         Dog2 dog2 = new Dog2();
      5.         dog2.eat();//吃骨头
      6.         dog2.action();
      7.         dog2.show();
      8.         //多态向上转型 - 不能调用本身的特有成员,可以调用父类的所有成员(遵守访问权限)
      9.             //为什么不能调用本身特有成员? 因为在编译阶段,能调用哪些成员,是由编译类型决定(说白了就是加载编译类型的成员变量)
      10.                 //Animal2是编译类型,Dog2是运行类型
      11.             //为什么animal2.eat();输出吃骨头不是吃东西? - 因为最终的的运行看子类的具体表现
      12.                 //因为最终的的运行看子类的具体表现什么意思? - 调用成员时还是按子类向父类的向上查找
      13.         Animal2 animal2 = new Dog2();
      14.         animal2.eat();//吃骨头
      15.     }
      16. }
      17. class Animal2{
      18.     public void eat(){
      19.         System.out.println("吃东西");
      20.     }
      21.     public void action(){
      22.         System.out.println("撒娇");
      23.     }
      24. }
      25. class Dog2 extends Animal2{
      26.     public void eat(){
      27.         System.out.println("吃骨头");
      28.     }
      29.     public void show(){
      30.         System.out.println("展示才艺");
      31.     }
      32. }
      复制代码
        

  • 多态向下转型:

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

      • 只能强转父类的引用,终于不是父类的对象
      • 强转的父类引用必须是和当前对象有关联的
      • 向下转型后,可以调用子类中所有的成员

      1. Animal2 animal2 = new Dog2();
      2. animal2.eat();//吃骨头
      3. //多态的向下转型 - 强转需要保持关联性
      4. //当初是Dog2向上转型为父类的animal2,那么向下转型也要保持这个关系
      5. Dog2 dog3 = (Dog2) animal2;
      6. og3.show();
      复制代码



  • 属性没有重写之说:

    • 属性的值看编译类型 -  
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         A a = new B();
      4.         System.out.println(a.name);//MIUI
      5.         B b = new B();
      6.         System.out.println(b.name);//Huawei
      7.     }
      8. }
      9. class A{
      10.     public String name = "MIUI";
      11. }
      12. class B extends A{
      13.     public String name = "Huawei";
      14. }
      复制代码

  • instanceOf比较操作符:

    • 用与判断对象的运行类型是否为XX类型或XX类型的子类型  
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         A a = new A();
      4.         System.out.println(a instanceof A);//真
      5.         A a2 = new B();
      6.         B b = new B();
      7.         System.out.println(b instanceof A);//真
      8.     }
      9. }
      10. class A{
      11.     public String name = "MIUI";
      12. }
      13. class B extends A{
      14.     public String name = "Huawei";
      15. }
      复制代码

  • java的动态绑定机制(重点):

    • 什么是动态绑定机制?

      • 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定
      • 当调用对象属性时,没有动态绑定机制,哪里声明哪里使用


    1. public class Test {
    2.     public static void main(String[] args) {
    3.         A a = new B();
    4.         //没有把B类中的sum()方法注销时的输出结果
    5.         System.out.println(a.sum());//220
    6.         System.out.println(a.sum1());//210
    7.         //把B类中的sum()方法注销后输出的结果
    8.          //为什么是210? 因为地态绑定机制的原因,调用到getl()时就回到运行类型的调用,没有该方法在往上寻找
    9.         System.out.println(a.sum());//210
    10.         System.out.println(a.sum1());//210
    11.     }
    12. }
    13. class A{
    14.     public int a = 100;
    15.     public int sum(){
    16.         return getl() + 10;
    17.     }
    18.     public int sum1(){
    19.         return a + 10;
    20.     }
    21.     public int getl(){
    22.         return a;
    23.     }
    24. }
    25. class B extends A{
    26.     public int a = 200;
    27. //    public int sum(){
    28. //        return a + 20;
    29. //    }
    30.     public int sum1(){
    31.         return a + 10;
    32.     }
    33.     public int getl(){
    34.         return a;
    35.     }
    36. }
    复制代码
  • 多态数组:

    • 什么是多态数组? 在一个数组中可以存放不同的子类
    • 案例:

    1. public class Test {
    2.     public static void main(String[] args) {
    3.         Person[] person = new Person[5];
    4.         person[0] = new Student("小白",18,"学生");
    5.         person[1] = new Teacher("老王",32,"老师");
    6.         for (int i = 0; i < person.length; i++) {
    7.             //show方法是重写的 - 但运行结果是根据运行类型
    8.             if(person[i] != null){
    9.                 String show = person[i].show();
    10.                 System.out.println(show);
    11.                 //向下转型,调用特有的成员
    12.                 if(person[i] instanceof Student){
    13.                     System.out.println(((Student)person[i]).study());
    14.                 }
    15.                 if(person[i] instanceof Teacher){
    16.                     System.out.println(((Teacher)person[i]).teach());
    17.                 }
    18.             }
    19.         }
    20.     }
    21. }
    22. class Person{
    23.     public Person(String name, int age) {
    24.         this.name = name;
    25.         this.age = age;
    26.     }
    27.     private String name;
    28.     private int age;
    29.     public String show(){
    30.         return name+"-"+age;
    31.     }
    32.     public String getName() {
    33.         return name;
    34.     }
    35.     public void setName(String name) {
    36.         this.name = name;
    37.     }
    38.     public int getAge() {
    39.         return age;
    40.     }
    41.     public void setAge(int age) {
    42.         this.age = age;
    43.     }
    44. }
    45. class Student extends Person{
    46.     public Student(String name, int age, String job) {
    47.         super(name, age);
    48.         this.job = job;
    49.     }
    50.     private String job;
    51.     public String show(){
    52.         return super.show()+"-"+job;
    53.     }
    54.     public String study(){
    55.         return super.getName()+"在收听java";
    56.     }
    57. }
    58. class Teacher extends Person{
    59.     public Teacher(String name, int age, String job) {
    60.         super(name, age);
    61.         this.job = job;
    62.     }
    63.     private String job;
    64.     public String show(){
    65.         return super.show()+"-"+job;
    66.     }
    67.     public String teach(){
    68.         return super.getName()+"给学生将java";
    69.     }
    70. }
    复制代码
Object顶级父类下的常见方法:


  • equals方法:

    • equlas:是Object类中的方法,默认(没被重写时)是判断引用类型的地址是否相等,子类往往重写该方法用与判断内容是否相等(如String和Integer)
    • 一般 equals 和 == 会进行一个比较(面试):

      • == :是一个比较运算符
      • == :即可以判断该基本数据类型,又可以判引用类型
      • ==:判断基本数据类型判断该的值,判断的是引用类型判断该的是地址  

    • 重写equals方法:
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         Person person1 = new Person("小白",18,'男');
      4.         Person person = new Person("小白",18,'男');
      5. //        System.out.println(person1.equals(person));//false(没有重写equals默认比较地址)
      6.         System.out.println(person1.equals(person));//true(重写equals后)
      7.     }
      8. }
      9. class Person{
      10.     public Person(String name, int age, char sex) {
      11.         this.name = name;
      12.         this.age = age;
      13.         this.sex = sex;
      14.     }
      15.     String name;
      16.     int age;
      17.     char sex;
      18.     public boolean equals(Object obj) {
      19.         //this代表的就是obj(自己调用我自己)
      20.         if(this == obj){
      21.             return true;
      22.         }
      23.         if(obj instanceof Person){
      24.             Person p = (Person)obj;
      25.             return this.name == p.name && this.age == p.age && this.sex == p.sex;
      26.         }
      27.         return false;
      28.     }
      29. }
      复制代码

  • hashCode方法: 

    • hashCode返回的是哈希码值,支持该方法是为了提高哈希表   
    • 哈希值主要根据地址类(但哈希值不完全等价于地址,因为Object的hashCode方法会根据不同的对象返回不同的整数) 
    • 两给引用,指向的是同一个对象,则哈希值肯定是一样,反知
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         Person person1 = new Person("小白");
      4.         Person person2 = new Person("小红");
      5.         System.out.println(person1.hashCode());//356573597
      6.         System.out.println(person2.hashCode());//1735600054
      7.     }
      8. }
      9. class Person{
      10.     public Person(String name) {
      11.         this.name = name;
      12.     }
      13.     String name;
      复制代码

  • toString方法: 

    • 默认返回:全类名+@+哈希值的十六进制
    • 一般子类重写用来返回对象的属性信息,打印对象或拼接对象时,都会该方法会自动调用
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         Person person1 = new Person("小白","打游戏");
      4. //        System.out.println(person1.toString());//默认输出
      5.         System.out.println(person1);//重写输出:Person{name='小白', hobby='打游戏'}
      6.     }
      7. }
      8. class Person{
      9.     public Person(String name, String hobby) {
      10.         this.name = name;
      11.         this.hobby = hobby;
      12.     }
      13.     String name;
      14.     String hobby;
      15.     @Override
      16.     public String toString() {
      17.         return "Person{" +
      18.                 "name='" + name + '\'' +
      19.                 ", hobby='" + hobby + '\'' +
      20.                 '}';
      21.     }
      22. }
      复制代码

  • finalize方法:

    • finalize方法是做什么的? 当对象被回收时,系统自动调用该方法(注意不是该方法用来回收对象,而是在被回收前做一些操作) 
    • 什么时候被回收?当对象没有引用指向它时,jvm认为该对象就是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁前会调用finalize方法
    • 垃圾回收机制?是由GC算法来决定(也就是说对象没引用的时候就马上销毁,而是由GC算法决定的),但是可以通过System.gc();来主动触发垃圾回收机制
      1. public class Test {
      2.     public static void main(String[] args) {
      3.         BaoMa baoMa = new BaoMa("宝马");
      4.         baoMa = null;
      5.         System.gc();//主动调用垃圾回收机制
      6.         System.out.println("程序退出");
      7.     }
      8. }
      9. class BaoMa{
      10.     public BaoMa(String name) {
      11.         this.name = name;
      12.     }
      13.     String name;
      14.     @Override
      15.     protected void finalize() throws Throwable {
      16.         System.out.println("销毁汽车"+name);
      17.         System.out.println("释放资源");
      18.     }
      19. }
      复制代码

 
 断点调试:


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

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

  •  
 
     
     

        
                    
 
   

 
  
  
 
        
   
 
 
 
      
 
 
     
 
   

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表