Java基础---面向对象

面向对象

面向对象编程的本质:以类的方式组织代码,以对象的组织(封装)数据

四大特征:封装、继承、多态、抽象(具有相同特征和行为的对象抽象

方法的深入

  1. 方法的定义

    • 修饰符

    • 返回类型

    • break和return的区别

      break用于switch或循环中跳出整个循环体

      return表示方法结束,返回一个结果,必须与返回值类型相同;

    • 方法名

    • 参数列表(参数类型,参数名)

    • 异常抛出 ???(以后讲)

  2. 方法的调用

    • 静态方法--可以直接通过类名.方法名调用

    ​ --两个静态方法可互相调用;两个非静态方法也可以互相调用

    • 非静态方法--不可直接调用,

      ---需要实例化(new一个对象),对象类型 对象名 = 对象值(new 对象类型)通过对象名.方法名来调用

      public class student {  //新建一个学生类
        //非静态方法
        public void say(){
            System.out.println("学生说话了");
        }
      }
      
      student zxy = new student();  //实例化
      zxy.say();   //对象名.方法
      

    • 形参和实参

    • 值传递和引用传递

    • this关键字

对象的创建和分析

类和对象的关系

--类是一种抽象的数据类型,对一类事物整体的描述,不能代表某一具体事务

--对象是抽象概念的具体实例

--创建对象:new关键字--本质是调用构造器

使用new时,除了分配空间外,还会给对象默认初始化以及对类中构造方法的调用;

student zxy = new student();   //调用了构造器
public student(){   }         //默认无参构造器
student wzh = new student(wangzihe); //调用构造器,有参构造
public student(String name){
        this.name = name;   //this.name指的是当前类中定义的name;第二个name是参数传进来的
    }
//如果定义了有参构造,那么无参构造必须显示写出来

--构造方法(构造器):与类名相同;没有返回值类型,也不能写void;完成数据初始化操作;

--内存分析:对象通过引用来操作:栈---->堆

封装

  • 数据的隐藏,应禁止直接访问一个对象的数据的实际表示,通过操作接口来访问
  • 属性私有(private)---get/set
  • 提供一些操作这些属性的方法:get(获取这个数据) set(给数据赋值)

继承

  • 本质:对某一批类的抽象,是类和类之间的关系,子类和父类之间

  • 关键字:extends(扩展)---子类是父类的扩展

  • Java中类只有单继承,没有多继承;----一个儿子只能有一个爸爸,一个爸爸有多个儿子

  • 私有的东西无法继承

  • 在Java中,所有类都默认直接或间接继承Object类

  • 在执行时,子类会默认调用父类的无参构造;

  • 被final修饰的类不能被继承;--final之后断子绝孙。。。

  • public class person    //父类
    public class student extends person  //子类/派生类--学生 is 人
    public class teacher extends person  //子类/派生类--老师 is 人
    

    super

    //主函数所在--测试类
    public class test {
        public static void main(String[] args) {
            student zxy = new student();
            zxy.test("hhhzxy");
        }}
    
    父类
    public class person {
        protected String name = "张二白";
    }
    
    子类
    public class student extends person {
        private String name = "zhangxiaoyang";
    
        public void test(String name){
            System.out.println(name);    //输出的是(hhhzxy)主函数中传的参数
            System.out.println(this.name); //输出的是(zhangxiaoyang)当前类中的name值
            System.out.println(super.name);//输出的是(张二白)父类的name值
        }
    }
    

    注意点:

    1)super调用父类的构造方法,必须在构造方法的第一个

    2)super必须只能出现在子类的方法中或构造方法中

    3)super和this不能同时调用构造方法

与this的区别:

​ 1)代表对象不同:

​ this:本身调用这个对象

​ super:代表父类对象的应用

​ 2)前提:

​ this:没有继承也可以用

​ super:只能在继承条件下可用

​ 3)构造方法

​ this():本类的构造

​ super():父类的构造

方法重写

需要有继承关系,子类重写父类的方法;子类和父类的方法必须一致,只是内容不同(方法体不同)

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大 public>protected>default>private
  4. 抛出的异常:范围可以被缩小,但不能扩大--(父亲欠了50万,你还了10万,还剩40万,你不能再欠了。。。)

-为什么要重写???---父类的功能,子类不一定需要或不一定满足;子类重写了父类的方法,执行时执行子类的

-什么方法不能重写:

1)static方法,属于类,不属于实例

2)被final(常量)修饰的方法

3)private方法

多态

什么是多态---同一个方法根据发送对象的不同而采用多种不同的行为方式

一个对象的实际类型是确定的---new student(); new person();

但可以指向对象的引用类型就不确定了,父类的引用指向子类

student s1 = new student();  //s1能调用的方法是自己的或继承父类的
person s2 = new student();   //person可以指向子类,但不能调用子类独有的方法
Object s3 = new student();  
 //对象能执行哪些方法,主要看对象左边的类型
 s1.run(); 
 s2.run(); //子类重写了父类的方法,执行子类的方法
 s2.eat(); //s2是person类型,无法调用student类里独有的方法
 ((student)s2).eat(); //把s2强制转化成student类型,可以调用student里独有的方法

注意事项:

  1. 多态是方法的多态

  2. 父类和子类,有联系,类型转换可能发生异常-- ClassCastException!

  3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象-father f1 = new son()

    instanceof (类型转换)

     Object >person >teacher
     Object >person >student
     System.out.println(X instanceof Y);//能不能编译通过,看X与Y是否有父子关系
     System.out.println(Object instanceof student);  //true
     System.out.println(student instanceof Object);  //true
     System.out.println(student instanceof teacher); //false
    

    子类转成父类,向上转型,自动;--可能丢失自己本来的一些方法

    父类转成子类,向下转型,强制转换;

    类型转换方便方法的调用,减少重复代码

    static详解

    1. 静态属性

      private static int age; //静态属性
      private double score; //非静态
      public static void main(String[] args) {
              student s1 = new student();
              System.out.println(student.age); //静态属性可直接用类名调用
              System.out.println(student.score); //非静态不能用类名直接调用
              System.out.println(s1.age);
              System.out.println(s1.score);
      
    2. 静态方法

      public void run() {
              go(); }  //静态方法和类一起加载,非静态方法里可以调用静态方法
      public static void go() {   
          }
       student.run(); //报错--非静态方法不能用类.方法名调用
       s1.run();
       student.go();  //静态方法可直接用类调用
      

      !!!是类的加载机制的问题,非静态都还没加载进来,自然不能直接用类调用,但静态和类一起加载,故可以调用

    3.静态代码块--最先执行(先于匿名代码块和构造方法),只执行一次

    4.匿名代码块和对象同时产生,在构造方法之前,可以赋一些初始值

    5.静态导入包-

    import static java.lang.Math.random;  //把Java.lang包中的Math的random()方法导入
    System.out.println(Math.random());//不导入的写法
    System.out.println(random());  //可以直接调用Math中的random()方法
    

抽象类和接口

抽象类(abstract class)

  • 对于抽象类的所有方法,继承了抽象类的子类,都必须要实现他的方法,除非子类也是抽象类,那就由下一代来实现。。。

  • 不能new这个抽象类,即不能创建实例;只能靠子类去实现它;

  • 抽象类里可以写普通方法,但抽象方法必须写在抽象类里;

  • 抽象类不能new,那存在构造器吗? ----存在,编译器添加默认的无参构造函数,只是不能直接创建抽象类的实例对象

  • 抽象类存在的意义?

  • //抽象类
    public abstract class Action {
        public abstract void dosomething(); //抽象方法--没有方法体,即具体的实现
    }
    

接口(interface)

  • 普通类:只有具体实现

  • 抽象类:具体实现和规范(抽象方法)都有!

  • 接口:只有规范!自己无法写方法~专业的约束!约束和实现分离:面向接口编程

  • 接口就是规范,定义一组规则---定义一些方法,让不同的人实现;

  • 接口不能被实例化~,接口没有构造方法(他连类都不是。。。)

  • 接口的本质是契约,像法律一样,制定好后大家遵守

  • 其实设计模式所研究的实际上就是如何合理的去抽象,所以设计模式都只针对具备抽象能力的语言(c++,java,c#等)

  • //通过interface定义一个接口,只声明方法,不实现(类型 方法名)
    public interface timeService {  
        void timer();
    }
    public interface UserService{
      void add(String nam);
      void delete(String nam);
      void update(String nam);
      void query(String nam);
    }
    
    //类 通过关键字implements实现接口,实现了接口的类必须重写接口中的方法(可以通过idea自动生成)
    public class UserServiceImpl implements UserService{  }
    //多继承---利用接口来实现
    public class UserServiceImpl implements UserService,timeService{}
    

内部类

  1. 成员内部类

    public class Outer {
        private int id = 10;
        public void out(){
            System.out.println("这是外部类的方法");}
        class  Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
            //内部类可以获得外部类的私有属性
            public void getId(){
                System.out.println(id);
    
            }
        }
    }
    
    
    //在测试类中
    public class test {
        public static void main(String[] args) {
            Outer outer = new Outer();  //外部类new一个对象
            Outer.Inner inner = outer.new Inner();  //通过外部类来实例化内部类。。。
            inner.in();
            inner.getId();
        }
    }
    

  2. 静态内部类

    public static class  Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }
            //内部类可以获得外部类的私有属性
            public void getId(){
                System.out.println(id);  //若类变成静态内部类,就无法获得私有属性了。。。还是类的加载机制
    
            }
        }
    
  3. 局部内部类

    public class Outer {
        //局部内部类---在一个方法里面定义的类
        public void method(){
            class Inner{ }
        }
    
  4. 匿名内部类

    class Apple {
        public void eat() {
            System.out.println("1");
        }
    }
    
    public class test {
        public static void main(String[] args) {
          new Apple().eat();    //没有名字初始化类,不用把实例存在变量里
          //正常情况下:Apple apple = new Apple(); apple.eat();
       }
    
  • 一个java类中可以有多个class类,但是只能有一个public class类

实战--人机猜拳游戏

项目开发步骤:

  1. 场景描述
  2. 四个找--找类、(若两个类很大量相同的属性和方法,可进一步抽象成父类)找属性、找方法、找关系
  3. 绘制类图、编写代码。
    • 两个类--玩家(人、机器)、裁判
    • 属性:玩家--名字、分数; 裁判:无
    • 方法:玩家--说名字、出拳 裁判:说规则、问名字、开始比赛、结束比赛宣布结果

总结:

  1. 玩家类是父类、抽象类--属性私有、定义抽象方法、通过get、set来对操作具体的属性值。
  2. 人和机器分别作为两个子类,要重写父类(抽象类)的方法。
  3. 定义裁判类,根据场景描述(效果图)来写裁判的方法。
  4. 测试。

注意:一般在创建类的时候顺序:私有属性->无参构造->有参构造->get/set方法->重写 (可以重写toString来方便测试)

posted @ 2022-01-10 19:40  二白--  阅读(61)  评论(0)    收藏  举报