面向对象基础

面向对象 & 面向过程

  • 面向过程思想

    • 步骤清晰简单,第一步做什么,第二步做什么...

    • 面向过程适合处理一些较为简单的问题

  • 面向对象思想

    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后才对某个分类下的细节进行面向过程的思索。

    • 面向对象适合处理复杂的问题,适合处理多人协作的问题!

  • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

什么是面向对象

  • 面向对象编程(Object-Oriented Programming,OOP)

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

 

  • 抽象

  • 三大特性

    • 封装

    • 继承

    • 多态

  • 从认识论考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象

  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。


 package Java高级班.oop;
 
 public class Dome01 {
     public static void main(String[] args) {
         
    }
     
     public String sayHello(){
         return "hello,world";
    }
     /*
     * 修饰符 返回值类型 方法名(...)
     * //方法体
     * return 返回值;
     * */
     //return 结束方法,返回一个结果!
     //break 跳出switch 结束循环
 //   public void hello(){
 //       return;
 //   }
     
 }
 package Java高级班.oop;
 
 public class Dome02 {
     public static void main(String[] args) {
         //实例化这个类 new
         //对象类型 对象名 = 对象值;
         Student student = new Student();
         student.say();
    }
     //和类一起加载的
     public static void a(){
        //b(); //报错
    }
     //类实例化之后才存在
     public void b(){
         
    }
 }
 package Java高级班.oop;
 //学生类
 public class Student {
 
 //   //非静态方法
     public void say(){
         System.out.println("学生说话了");
    }
 //静态方法---->直接调用无需new对象
 //public static void say(){
 //   System.out.println("学生说话了");
 //}
 
 }
 package Java高级班.oop;
 
 public class Dome03 {
     public static void main(String[] args) {
         //实际参数和形式参数的类型要对应!
       int add = Dome03.add(1,2);
         System.out.println(add);
    }
     
     public static int add(int a,int b){//占位符
         return a + b;
    }
 }
 package Java高级班.oop;
 //值传递
 public class Dome04 {
     public static void main(String[] args) {
         int a = 1;
         System.out.println(a);//1
 
         Dome04.change(a);
 
         System.out.println(a);//1
    }
     //返回值为空
     public static void change(int a){
         a = 10;
    }
 }
 package Java高级班.oop;
 
 //引用传递 对象,本质还是值传递
 
 //对象 内存
 public class Dome05 {
 
     public  void change(Person person){
         //person是一个对象:指向是--->
         person.name = "二狗子";
    }
     public static void main(String[] args) {
         Dome05 dome05 = new Dome05();
         Person person = new Person();
         System.out.println(person.name);//null
         dome05.change(person);
         System.out.println(person.name);//二狗子
    }
 }
 //定义了一个Person类,有一个属性:name
 class Person{
     String name;//null
 }

类和对象的关系

  • 类是一种抽象的数据类型,它是对某一具体事物整体描述/定义,但是并不能代表某一个具体事物。

    • 动物 植物 手机 电脑

    • Person类 Pet类 Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为

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

    • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。

    • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。


创建与初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

    • 必须和类的名字相同

    • 必须没有返回类型,也不能写void

  • 构造器必须要掌握

 package Java高级班.oop.opp2;
 //学生类
 public class Student {
     //属性:字段
     String name;//这是抽象的模板不能写死
 //   String name = "xiaoming";//这是抽象的模板不能写死
     int age;
 
     //方法
     public void study(){
         System.out.println(this.name + "在学习");
    }
     
     //学程序好?对世界进行更好的建模!
 }
 package Java高级班.oop.opp2;
 //一个项目应该只存在一个main方法
 public class Application {
     public static void main(String[] args) {
       //类是抽象的,实例化
         //类实例化后会返回一个自己的对象!
         //student对象就是一个Student类的具体实例!
         Student xiaoming = new Student();
         Student xh = new Student();
         System.out.println(xiaoming.name);
         System.out.println(xiaoming.age);
 
         xiaoming.name = "小明";
         xiaoming.age = 3;
 
         System.out.println(xiaoming.name);
         System.out.println(xiaoming.age);
 
         xh.name = "小红";
         xh.age = 3;
 
         System.out.println(xh.name);
         System.out.println(xh.age);
    }
 }

补充

保留n位小数

方法一:String的format方法(推荐)

 

double f = 111231.5585;

 

System.out.println(String.format("%.2f", f));

 //        String i = "";
 //       System.out.println("*************");
 //       System.out.println(i);//null和String里的""不同
 package opp1022;
 
 public class Person {
     //一个类即使什么都不写,它也会存在一个方法
     //显示定义的构造体
     String name;
     int age;
 
     public Person(String name, int age) {
         this.name = name;
         this.age = age;
    }
 
     //这个是Alt + Insert 选择Select None生成的
 //   public Person() {
 //   }
 
     //   //实例化初始值
 //   //1.使用new关键字,本质是在调用构造器
 //   //2.用来初始化值
     //这个是Alt + insert 选择ok生成的
     public Person(String name) {
         this.name = name;
    }
 //   public Person() {//无参
 //       //name = "二狗子";
 //   }
 //
 //   //有参构造:一旦定义了有参构造,无参就必须显示定义
 //   public Person(String name){
 //       this.name = name;
 //   }
     //alt + insert//Code->Generate->Constructor
 
 }
 /*public class Application {
     public static void main(String[] args) {
         Person person = new Person();
         System.out.println(person.name);//null
 //       String i = "";
 //       System.out.println("*************");
 //       System.out.println(i);//null和String里的""不同
     }
 }
 
 
       构造器:
            1. 和类名相同
            2. 没有返回值
         作用:
            1. new 本质在调用构造方法
            2. 初始化对象的值
       注意点:
            1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
 
            Alt + Insert
            是代表当前类的     =     一般是参数传的值
            this.             =       value
 
 
 */


小结(this 指当前类的对象,构造函数互相调用用this()

,可有参可无参,必须放在构造函数中的第一行)

  1. 类与对象

    类是一个模板:抽象的    对象是一个具体的实例

  2. 方法

    定义,调用!

  3. 对象的引用

    引用类型:        基本类型(8)

      对象是通过引用来操作的 栈--->堆(地址)

  1. 属性:字段 Field 成员变量

    默认初始化:

          数字:0 0.0

          char:u0000

          boolean:false

          引用:null

    修饰符 属性类型 属性名 = 属性值!

  2. 对象的创建和使用

    • 必须使用new关键字创造对象,构造器  Person ergouzi = new Person();

    • 对象的属性 ergouzi.name

    • 对象的方法 ergouzi.sleep()

  3. 类:

    • 静态的属性 属性

    • 动态的行为 方法

    封装,继承,多态


封装

  • 该露的露,该藏的藏

    • 我们程序设计要求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

  • 封装(数据的隐藏)

    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

  • 记住这句话就够了:属性私有,get/set

 package opp1024;
 /*
 * 1.提高程序的安全性保护数据
 * 2.隐藏代码的细节
 * 3.统一接口
 * 4.系统可维护性增加
 * */
 public class StudentTest {
     public static void main(String[] args) {
         Student student = new Student();
         //student.name = "";
         //一个疑问 a的返回值类型是String,b本身就是String类型,为什么a单独一条语句不报错,而b却报错?
 //       student.getName();//a
 //       "hvhj";//b
         
         //方法名,参数列表
         System.out.println(student.getName());
         student.setName("二狗子");
         System.out.println(student.getName());
 
         student.setAge(999);//不合法
         System.out.println(student.getAge());
 
         student.setAge(70);//合法
         System.out.println(student.getAge());
    }
 }
 package opp1024;
 //类
 public class Student {
     //名字
     private String name;
     //学号
     private  int id;
     //性别
     private char sex;
     //年龄
     private int age;
 
     //提供一些可以操作这个属性的方法!
     //提供一些public的get,set方法
     //正常情况下getSet不会用重载
 
     //get 获得这个数据
 
     public String getName() {
         return name;
    }
 
     public int getAge() {
         return age;
    }
 
     //set 给这个数据设置值
 
     public void setName(String name) {
         this.name = name;
    }
 
     public void setAge(int age) {
         if (!(age > 120 || age < 0)) {
             this.age = age;
        }else {
             age = 3;
        }
         this.age = age;
    }
 //学习()
 
     //睡觉()
 }

继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

  • extends的意思是"扩展"。子类是父类的扩展。

  • Java中类只有单继承,没有多继承!

  • 继承是类与类之间的一种关系。除此以外,类与类还有依赖,组合,聚合等。

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extend来表示。

  • 子类和父类之间,从意义上将应该具有"is a"的关系。

 

  • object类

  • super

  • 方法重写

 package opp1024;
 //小学生 Pupil is a Person 人
 //老师 Teacher is a Person 人
 
 //继承是最核心的东西,相当于宏观的把握;封装是关于底层的;多态有继承的前提
 
 //Person 人:父类
 
 //在Java中所有的类,都默认直接或者间接继承Object
 public class Person /*(extends Object)---> 正常情况下可以省略掉*/{
 //
 //   //public : 他爸爸给儿子的
 //   //protected
 //   //default ---> 直接不用写
 //   //private: 他爸爸自己的临死也没给儿子的 ---> 一般属性才是私有的
 //
 //   private int money = 1_000_000_000;
 //   //private int money = 1_000_000_000;
 //
 //   //前提都是public的方法
 //   public void say(){
 //       System.out.println("说了一句话。");
 //   }
 //
 //   public int getMoney() {
 //       return money;
 //   }
 //
 //   public void setMoney(int money) {
 //       this.money = money;
 //   }
 }
 package opp1024;
 //老师 Teacher is a Person 人
 public class Teacher extends Person{
 }
 package opp1024;
 //小学生 Pupil is a Person 人 派生类,子类
 public class Pupil extends Person{
 }
 
 //Ctrl + H :打开树
 ////这个叫组合
 //public class Pupil {
 //   Person person;
 //}
 package opp1024;
 
 public class Application {
     public static void main(String[] args) {
         Pupil pupil = new Pupil();
         //pupil.say();
         //System.out.println(pupil.money);//private不能继承
 
         Person person = new Person();
         //person.
    }
 }

Super详解

super注意点

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

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

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

vs this

  • 代表的对象不同:

    • this: 本身调用这个对象

    • super:代表父类对象的引用

  • 前提

    • this:没有继承也可以使用

    • super:只能在继承条件下才可以使用

  • 构造方法

    • this();本类的构造

    • super();父类的构造

 package opp1024;
 public class Pupil extends Person{
 //   Person("qwer");
 //   private String name = "张大仙";
 //
 
     public Pupil() {
         //隐藏代码:默认调用了父类的无参构造
         //调用父类构造器,必须要在子类构造器的第一行
         //包括this也一样调用自己的构造器也是第一行
         //一个类只要写了有参构造就把无参构造加上
         //只要写了有参构造,无参构造就没了,除非自己再写一个
         //如果不写无参构造子类也没法写父类的无参构造
         //如果父类没写无参仅写了有参,子类调用父类的无参调用
         // 不了,但调用有参却可以调用。
        super("vg");
        //super();//--->会报错
         //this("大仙");
         System.out.println("Pupil无参构造被执行了");
    }
 
 //   public Pupil(String name) {
 //       this.name = name;
 //   }
 
     public void print(){
         System.out.println("Pupil");
    }
 
     public void test1(){
         print();
         this.print();
         super.print();
    }
 
     public void test(String name){
         System.out.println(name);
         System.out.println(this.name);
         System.out.println(super.name);
    }
 }
 package opp1024;
 public class Person{
     protected String name = "二狗子";
 
 //   public Person() {
 //       System.out.println("Person无参执行了");
 //   }
 
     public Person(String name) {
         this.name = name;
    }
 
     //私有的东西无法被继承
     //private void print(){
     public void print(){
         System.out.println("Person");
    }
 }
 package opp1024;
 public class Teacher extends Person{
 }
 package opp1024;
 
 import java.util.Scanner;
 
 public class Application {
     public static void main(String[] args) {
         Pupil pupil = new Pupil();
         //pupil.test("张冰心");
         //pupil.test1();
    }
 }

对象方法和类方法的区别

  • 对象方法是你必须实例化该对象,才可以使用相对应权限的方法。

  • 类方法是你不需要实例化该对象,也可以使用该方法,类方法也叫静态方法


重写

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

  • 重写是继承里的一个概念,重载是一个类里的概念

  • 特点

    • 方法名必须相同

    • 参数列表必须相同

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

    • 子类到父类,子类修饰符限定范围比父类大,比如子类是protected的话,父类只能是default或protected,但是子类异常范围更小

    • 抛出的异常:范围可以被缩小但不能被扩大 ClassNotFoundException --> Exception

    • 重写异常抛出范围不能大于父类

  • 重写:子类的方法和父类必须要一致:方法体不同

 

  • 为什么需要重写:

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

      • Alt + Insert :override;

  • static是类方法,方法调用只和左边有关且不属于重写范畴,重写是非static方法的重写

 package opp1024.dome;
 
 public class Application {
 
     //静态方法和非静态方法的区别很大
     //没有static时,b调用的是对象的方法,
     //而b是A new出来的对象,因此调用了A的
     //方法,因为静态方法是类的方法,
 
     //非静态:重写
     public static void main(String[] args) {
 
         //类方法的调用只和左边定义的数据类型有关
         A a = new A();
         a.test();
 
         //父类的引用指向子类
         B b = new A();//子类重写了父类的方法
         b.test();
    }
 }
 package opp1024.dome;
 //继承关系
 public class A extends B{
     //Override 重写
     //@Override//注解,有功能的注释
      protected void test() {
         System.out.println("A=>test()");
    }
 }
 package opp1024.dome;
 
 
 //重写都是方法的重写和属性无关
 //重写都是非静态方法,与静态方法无关
 //idea中出现那个o红色向上的箭头说明确实重写了
 //重写关键词是public不能是private
 public class B {
     void test(){
 //   private void test(){//编译出错
         System.out.println("B=>test()");
    }
 }

多态

  • 动态编译:执行过程中才可以确定类型,程序可拓展性增强

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式。

  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类或者有关系的类)

 

  • 多态存在的条件

    • 有继承关系

    • 子类重写父类方法

    • 父类引用指向子类对象

 

  • 注意:多态是方法的多态,属性没有多态性

  • instanceof 类型转换--->引用类型     判断一个对象是什么类型

  • 基本数据类型是看容量关系,引用数据类型看子类和父类的关系

 package opp1025;
 
 public class Person {
     public void run(){
         System.out.println("run");
    }
 }
 package opp1025;
 
 public class Student extends Person {
     @Override
     public void run() {
         System.out.println("son");
    }
 
     public void eat(){
         System.out.println("eat");
    }
 }
 
 /*
 * 多态注意事项
 *   1.多态是方法的多态,属性没有多态
 *   2.父类和子类,有联系,即使强制转换类型,也得互相之间有联系父类为大,子类为小
 *   父类变子类叫向下类型转换,子类变父类叫向上类型转换
 *   类型转换异常 ClassCastException!
 *   3.多态存在条件a.继承关系b.方法需要重写c.父类引用指向子类对象
 *
 *       1.static方法属于类,不属于实例
 *       2.final 常量
 *       3.private方法
 *       */
 package opp1025;
 
 public class Application {
     public static void main(String[] args) {
         //一个对象的实际类型是确定的
         //new Student();
         //new Person();
         //可以指向的引用类型就不确定了
 
 
         //Student子类型 能调用的方法都是自己的或继承父类的
         Student s1 = new Student();
 
         //父类的引用指向子类的类型
         //父类型Person虽然可以指向子类,但不能调用子类独有的方法,除非强制类型转换,
         //强制转换依然遵循大到小转换 父类比子类大嘛
         Person s2 =  new Student();
         Person s4 = new Person();
         Object s3 = new Student();
 
         //子类重写了父类的方法,执行子类的方法
         s2.run();
         s1.run();
        ((Student)s4).run();
 
         //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
         s1.eat();
        ((Student) s2).eat();
    }
 }

instanceof 和类型转换

 package opp1025;
 
 public class Test {
     public static void main(String[] args) {
         //类型之间的转换:基本类型转换 高-->低 64 32 16 8
         //               引用类型转换 高-->低 父 子
         // 高         低
         Animal animal = new Dog();
 
         //animal将这个对象转换为Dog类型,我们就可以使用Student类型的方法了。
         //animal.go();//报错
         //第一种强转
 //       ((Dog) animal).go();
 
         //第二种强转
 //       Dog dog = (Dog)animal;
 //       dog.go();
 
         Dog dog = new Dog();
         dog.go();
         //子类转换为父类可能会丢失一些方法
         //低(子)转高(父)时,由于子已经继承了父的所有,所以删去自己的后自然而然就可以转换为父类的,
         //而父想转子,则需要重新开辟只属于子的空间,则需要强制转换。
         Animal animal1 = dog;
         //((Dog) animal).go();
    }
 }
 
 /*
 * 前提:
 *   父类的引用指向类的对象
 *   把子类转换成父类,向上转型 子类转换为父类可能会丢失一些方法,可能会用不了子类的方法
 *   把父类转换成子类,向下转型 强制转换 父类强转子类才可以调用子类的方法,并不是丢失但会损失精度,不转换无法调
 *   用子类特有方法,和丢失没有关系,父类本身不含子类特有方法,内存不够接收不了,
 *   精度是各种数据类型的位宽
 *   */
 
 //   Object object = new Dog();
 //       System.out.println(object instanceof Dog);
 //               System.out.println(object instanceof Cat);
 //               System.out.println(object instanceof Object);
 //               System.out.println(object instanceof Animal);
 //               System.out.println(object instanceof String);
 //
 //               //能不能编译通过 看左边的类型(必须是引用类型)
 //               //在编译通过的情况下 实际判断对象变为=右边的类型
 //               //System.out.println(X instanceof Y);
 //
 //               System.out.println("+++++++++++++++++++++++++++++++++++++++++++++");
 //
 //               Animal animal = new Dog();
 //               System.out.println(animal instanceof Dog);
 //               System.out.println(animal instanceof Cat);
 //               System.out.println(animal instanceof Object);
 //               System.out.println(animal instanceof Animal);
 //
 //               //关键看new的是什么,new Dog就看Dog这条线,
 //               // dog向上只有一个爹,一个爷,一个曾爷...向下可能有一个娃或者多个娃
 //               //System.out.println(animal instanceof String);//Person和String没有继承关系;编译报错
 //
 //               System.out.println("+++++++++++++++++++++++++++++++++++++++++++++");
 //               Dog dog = new Dog();
 //               System.out.println(dog instanceof Dog);
 //               //System.out.println(dog instanceof Cat);
 //               System.out.println(dog instanceof Object);
 //               System.out.println(dog instanceof Animal);
 package opp1025;
 
 public class Cat extends Animal {
 }
 package opp1025;
 
 public class Dog extends Animal {
     public void go(){
         System.out.println("go");
    }
 }
 package opp1025;
 
 public class Animal {
     public void run(){
         System.out.println("father");
    }
 }

补充点

  • this表示这个类的当前实例,super表示父类的当前实例,static是属于类的,this是类的一个对象,当然调用了不了他,static太牛了,只有类名可以调用它,static叫静态方法,也叫类方法,就是在程序启动的时候,就会为这个方法分配一块内存空间,所以什么时候都可以调用这个方法

  • this为什么不能在静态方法中使用?

    • 静态方法是存放在方法区中的,此时使用this不能获取到当前类的地址而在类的普通方法中使用this,就能得到当前对象在堆中的地址


Java中匿名代码块、静态代码块以及构造方法的执行顺序

 package opp102502;
 
 
 public class Test {
 
 
    {
         //匿名代码块用来赋初值
         System.out.println("匿名代码块");
    }
 
     static {
         //静态代码块只执行一次
         System.out.println("静态代码块");
    }
 
     public Test(){
         //构造方法
         System.out.println("构造方法");
    }
 
     public static void main(String[] args) {
         Test test1 = new Test();
         System.out.println("=====分割线======");
         Test test2 = new Test();
 
    }
 }

静态代码块

匿名代码块

构造方法

=====分割线======

匿名代码块

构造方法

 package opp102502;
 
 //static
 //通过final继承的类就没有子类了-->没后代了
 //public class Student extends Person{
 public class Student {
     private static int age;//静态变量 多线程用
     private double score;//非静态变量
     public void run(){
         System.out.println("run");
         //非静态方法可以调用静态方法的所有东西
         //go();
    }
 
     public static void shout(){
         System.out.println("汪!汪!汪");
    }
 
     public static void go(){
         System.out.println("go");
         //静态方法可以调用静态方法的所有东西
         shout();
    }
     public static void main(String[] args) {
         Student student = new Student();
         student.run();
         go();
         student.go();
         Student.go();
         //this.run();
         System.out.println(student.age);
         //System.out.println(this.age);
 
         //为什么this.go()不可以而类名.go()就可以呢
         //this.go();
         Student.go();
 //       Student student = new Student();
 //
 //       System.out.println(Student.age);//类变量
 //       // System.out.println(Student.score);
 //
 //       System.out.println(student.age);
 //       System.out.println(student.score);
    }
 }
 package opp102502;
 //import static java.lang.Math.random;
 
 //静态导入包
 import static java.lang.Math.PI;
 import static java.lang.Math.pow;
 import static java.lang.Math.random;
 
 //通过final继承的类就没有子类了-->没后代了
 public class Application {
     public static void main(String[] args) {
         System.out.println(random());
         System.out.println(PI);
         System.out.println(pow(2, 3));
    }
 }

抽象类

  • abstract修饰符可以用来修饰方法也可以用来修饰类,如果修饰方法,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

  • 抽象类中可以没有抽象方法,但有抽象方法的类一定要声明为抽象类。

 

  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

 

  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

 package opp102503;
 //abstract 抽象类
 public abstract class Action {
 
     //约束——有人帮我们实现
     //abstract,抽象方法,只有方法名字,没有方法实现。
     public abstract void doSomething();
 }
 //类中存在不抽象的方法,但是一旦有抽象的方法就得把类声明为抽象类
 //抽象方法必须在抽象类中
 //抽象的抽象:约束
 
 //思考? 抽象类不能new一个对象,那么存在构造器吗? 答 存在
 //抽象类存在的意义是什么? 抽象出来-->提高开发效率,可扩展性提高。
 //
 // Source code recreated from a .class file by IntelliJ IDEA
 // (powered by Fernflower decompiler)
 //
 
 package opp102503;
 
 public abstract class Action {
     public Action() {
    }
 
     public abstract void doSomething();
 }
 package opp102503;
 //抽象类的所有方法,继承它的子类,都必须要实现它的抽象方法,普通方法不一定要重写
 //如果子类本身是抽象的就没必要实现继承来的抽象方法,让子子类去实现
 
 //总结:继承自抽象类的子类,必须实现父类的所有抽象方法
 
 //extends 单继承   Java中接口可以多继承!
 public class A extends Action {
     @Override
     public void doSomething() {
 
    }
     //抽象类特点
     //1.不能new这个抽象类,只能靠子类实现它,约束!
 }
 package opp102503;
 
 public class Application {
     public static void main(String[] args) {
         //new Action();
    }
 }

接口

  • 普通类:只有具体实现

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

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

 

  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想。如果你是天使则必须能飞。如果你是汽车,则必须能跑。如果你是好人则必须干掉坏人。如果你是坏人则必须欺负好人。

  • 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

  • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++,Java,C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。

声明类的关键字是class,声明接口的关键字是interface

 package opp102504;
 
 //抽象的思维 Java 架构师
 
 //interface 定义的关键字 接口都需要有实现类
 public interface UserService {
     //接口中的所有定义其实都是抽象的public
 
     //public abstract都不必写
     //public abstract void run();
     //接口定义的方法都是public abstract
     
     //一般没人在接口里定义常量
     //常量~public static final
     public static final int AGE = 99;
 
     void add(String name);//增
     void delete(String name);//删
     void update(String name);//改
     void query(String name);//查
 
 }
 package opp102504;
 
 //public class UserServiceImpl {//implement v.实现 n.工具//java中implements是关键字
 
 //抽象类:extends 单继承
 //类可以实现接口 implements 接口 多继承
 //实现了接口的类,就需要重写接口的方法
 //利用接口实现(伪)多继承
 public class UserServiceImpl implements UserService,TimeService{
     @Override
     public void add(String name) {
 
    }
 
     @Override
     public void delete(String name) {
 
    }
 
     @Override
     public void update(String name) {
 
    }
 
     @Override
     public void query(String name) {
 
    }
 
     @Override
     public void timer() {
 
    }
 }
 package opp102504;
 
 public interface TimeService {
     void timer();
 }
  • 总结作用:

    • 约束

    • 定义一些方法让不同的人实现       10   --->

    • public abstract

    • public static final

    • 接口不能被实例化,接口中没有构造方法

    • 抽象类可以有构造器 需要通过构造链来调用

    • implements可以实现多个接口

    • 必须要重写接口中的方法

    • 总结博客


内部类

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

 

  • 成员内部类

  • 静态内部类

  • 局部内部类

  • 匿名内部类

正常的(允许多个public出现在内部)

 package opp102505;
 
 public class Outer {
 
     private int id = 10;
     public void out(){
         System.out.println("这是外部类的方法");
    }
 
 
     public class Inner{
         public void in(){
             System.out.println("这是内部类的方法");
        }
 
         //获得外部类的私有属性
         public void getID(){
             System.out.println(id);
        }
    }
 }
 package opp102505;
 
 public class Application {
     public static void main(String[] args) {
         //new
 
         Outer outer = new Outer();
 
         //通过这个外部类来实例化内部类
         Outer.Inner inner = outer.new Inner();
         inner.in();
         inner.getID();
    }
 }

静态的

 package opp102505;
 
 public class Outer {
 
     private int id = 10;
     public void out(){
         System.out.println("这是外部类的方法");
    }
 
 
     public static class Inner{
         public void in(){
             System.out.println("这是内部类的方法");
        }
 
         //获得外部类的私有属性
         public void getID(){
             //一旦成为静态类先访问内部类,id未访问所以报错
             //System.out.println(id);
        }
    }
 }

局部内部类

 public class Outer {
 
     //局部内部类 不允许有public类
     public void method(){
         class Inner{
             public void in(){
                 
            }
             
        }
    }
 }

匿名内部类

 package opp102505;
 
 public class Test {
     public static void main(String[] args) {
         //有名字初始化对象
         Apple apple = new Apple();
 
         //没有名字初始化类,不用将实例保存在变量中
         new Apple().eat();
 
         //会返回一个UserService对象,但是这个类也没有名字!
         UserService userService = new UserService(){
             @Override
             public void hello() {
 
            }
        };
 
         //匿名内部类
         new UserService(){
             @Override
             public void hello() {
 
            }
        };
 
    }
 }
 
 interface UserService{
     void hello();
 }
 
 class Apple{
     public void eat(){
         System.out.println("1");
    }
 }







posted @ 2020-10-25 20:49  0基础学Java  阅读(84)  评论(0)    收藏  举报