day07 7.1 Java中的面向对象之类与对象

day07 7.1 Java中的面向对象之类与对象

【一】类与对象

【1】类定义规范

  • 类与对象的关系
    • 类 是实体对象的概念模型,笼统的,不具体的,
      • 比如人类、动物类、鸟类
    • 对象 又称为实体,类具体化的表现
      • 小红/小明
      • 小猫一号/小狗一号
    • 对象中有属性,有方法
      • 不同对象属性是独有的
      • 方法是共有的
  • 类定义规范
// [] :内的内容可以不写 | :左右的内容表示或 [public][abstract|final] class 类名class_name [extends 继承的类名] [implements 实现的接口名]{ // 定义成员属性 属性类型1 属性名1; // String name; 属性类型2 属性名2; // int age; // 定义静态属性(类属性) private String name; // 定义类成员方法 public int add(int a, int b){ return a+b; } // 定义静态方法(类方法) public static void speak(){ System.out.println("说话") } }

public:表示类是公有的

java文件的文件名必须是public class 类名

abstract:抽象类

final:类如果被 final 修饰 ,这个类不能被别的类所继承

extends:继承某个父类

implements:实现的接口

(1)类的定义

public class Person { // 定义成员属性 private String name; // 定义成员属性 public int age; // 定义静态属性 public static int sex; // 定义类成员方法 // void:方法没有返回值 public void speak() { System.out.println("说话了!"); } // 静态方法 public static run() { System.out.println("跑起来了!"); } }

(2)对象的实例化

import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; public class Demo01 { public static void main(String[] args) { // 因为在同一个包下,所以可以直接引用 // (1)实例化类对象 p Person p = new Person(); // (2)修改对象属性 // 由于 name 是由 private 修饰 // 所以无法通过对象 修改该属性 p.age = 18; System.out.println(p); // Person@1b6d3586 // (3)调用对象方法 p.speak(); // 说话了! } }

【2】Java的类属性

  • 在类中有属性
    • 成员属性
      • 只要不被static修饰的,就是成员属性,他是属于对象的,需要对象来调用
    • 静态变量
      • 只要 static修饰的,需要类或类实例的对象来调用
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; //public class Demo01 { // // public static void main(String[] args) { // // 因为在同一个包下,所以可以直接引用 // // (1)实例化类对象 p // Person p = new Person(); // // // (2)修改对象属性 // // 由于 name 是由 private 修饰 // // 所以无法通过对象 修改该属性 // p.age = 18; // System.out.println(p); // // Person@1b6d3586 // // // (3)调用对象方法 // p.speak(); // // 说话了! // } //} public class Demo01 { public static void main(String[] args) { // 类属性 // (1)实例化类得到类对象 Person p = new Person(); // 对象的属性 ----> 不被static修饰的 p.hobby = "music"; p.age = 18; Person p1 = new Person(); // 对象的属性 ----> 不被static修饰的 p1.hobby = "sport"; p1.age = 29; // 每个对象都有自己的属性,因此打印的内容不一样 System.out.println(p.hobby); System.out.println(p1.hobby); // (2)静态成员:被static修饰的,属于类 // 通过对象,修改静态成员,但是他是属于类的,都会受影响 p.sex = 2; p1.sex = 1; System.out.println(p.sex); // 2 // 1 System.out.println(p1.sex); // 2 // 1 // 类来修改静态属性,一般是用类来修改静态属性 Person.sex = 3; System.out.println(p.sex); // 3 System.out.println(p1.sex); // 3 } }
public class Person { // 定义成员属性 private String name; // 定义成员属性 public String hobby; public int age; // 定义静态属性 public static int sex; // 定义类成员方法 // void:方法没有返回值 public void speak() { System.out.println("说话了!"); } // 静态方法 public static void run() { System.out.println("跑起来了!"); } }
  • 在Python中年对象的属性只能对象来调用
  • 在Python中年类的属性只能类来调用

【3】成员方法

  • 类中没有被static修饰的方法,绑定给类的,需要类来调用。
  • Python中有绑定给对象的方法,绑定给类的方法

    • Python的类中,不加任何装饰器的的方法是绑定给对象的

      java:public void Speak(){}
    • Python的类中,使用@classmethod修饰的,是绑定给类的方法

      java:public static void Speak(){}
public class Demo01 { public static void main(String[] args) { // 静态方法和成员方法 Person p = new Person(); p.speak(); // 对象的方法 // p.run();//类的方法,正常不是对象来调用,而是类来调用 Person.run(); } }
public class Person { // 定义成员属性 private String name; // 定义成员属性 public String hobby; public int age; // 定义静态属性 public static int sex; // 定义类成员方法 // void:方法没有返回值 // 没有被 static 修饰 public void speak() { System.out.println("说话了!"); } // 静态方法 // 被 static 修饰 public static void run() { System.out.println("跑起来了!"); } }

【4】构造方法

  • 在Python中

    __init__方法完成对象的初始化

  • 在Java中

    完成对对象的初始化,向对象中添加内容

    可以存在多个,使用哪种初始化方式,就会触发那种构造方法

public class Demo01 { public static void main(String[] args) { // 构造方法 // (1)触发无参构造方法 Person person = new Person(); // 实例化对象,但是不向对象中添加参数 // 会触发Person类的无参构造方法,完成初始化 // 一旦执行,person中的 name 就完成了初始化 变成了 dream System.out.println(person.name); // 我正在开始执行! // dream // (2)触发有参构造方 Person p = new Person("mengmeng"); System.out.println(p.name); // 我是有参构造方法,形参为1个 // mengmeng // (3)触发有参构造方法 Person p1 = new Person("CHIMENG", 19); System.out.println(p1.name); System.out.println(p1.age); // 我是有参构造方法,形参为2个 // CHIMENG // 19 } }
public class Person { // 定义成员属性 // private String name; // 定义成员属性 public String hobby; public String name; public int age; // 定义静态属性 public static int sex; // 定义类成员方法 // void:方法没有返回值 // 没有被 static 修饰 public void speak() { System.out.println("说话了!"); } // 静态方法 // 被 static 修饰 public static void run() { System.out.println("跑起来了!"); } // 构造方法 // 无参构造方法 public Person() { System.out.println("我正在开始执行!"); this.name = "dream"; } // 有参构造方法 public Person(String name) { System.out.println("我是有参构造方法,形参为1个"); this.name = name; } // 有参构造方法 public Person(String name, int age) { System.out.println("我是有参构造方法,形参为2个"); this.name = name; this.age = age; } }

【5】this关键字

  • this是写在类中的成员(对象)方法中
  • [static修饰的方法中,即静态方法中,没有this]
public class Demo01 { public static void main(String[] args) { // 构造方法 // (1)触发无参构造方法 Person person = new Person(); // 实例化对象,但是不向对象中添加参数 // 会触发Person类的无参构造方法,完成初始化 // 一旦执行,person中的 name 就完成了初始化 变成了 dream System.out.println(person.name); // 我正在开始执行! // dream // (2)触发有参构造方 Person p = new Person("mengmeng"); System.out.println(p.name); // 我是有参构造方法,形参为1个 // mengmeng // (3)触发有参构造方法 Person p1 = new Person("CHIMENG", 19); System.out.println(p1.name); System.out.println(p1.age); // 我是有参构造方法,形参为2个 // CHIMENG // 19 // this 触发 // 谁调用方法就是谁 person.Sleep(); //dream //睡觉中..... p.Sleep(); //mengmeng //睡觉中..... p1.Sleep(); //CHIMENG //睡觉中..... } }
public class Person { // 定义成员属性 // private String name; // 定义成员属性 public String hobby; public String name; public int age; // 定义静态属性 public static int sex; // 定义类成员方法 // void:方法没有返回值 // 没有被 static 修饰 public void speak() { System.out.println("说话了!"); } // 静态方法 // 被 static 修饰 public static void run() { System.out.println("跑起来了!"); } // 构造方法 // 无参构造方法 public Person() { System.out.println("我正在开始执行!"); this.name = "dream"; } // 有参构造方法 public Person(String name) { System.out.println("我是有参构造方法,形参为1个"); this.name = name; } // 有参构造方法 public Person(String name, int age) { System.out.println("我是有参构造方法,形参为2个"); this.name = name; this.age = age; } // this 关键字 public void Sleep() { System.out.println(this.name); System.out.println("睡觉中....."); } }

【6】访问控制符

访问范围 private friendly(默认) protected public
同一个类 可访问 可访问 可访问 可访问
同一包中的其他类 不可访问 可访问 可访问 可访问
不同包中的子类 不可访问 不可访问 可访问 可访问
不同包中的非子类 不可访问 不可访问 不可访问 可访问
//1 private private 修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。因此,private 修饰符具有最高的保护级别 //2 friendly(默认) 如果一个类没有访问控制符,说明它具有默认的访问控制特性。这种默认的访问控制权规定,该类只能被同一个包中的类访问和引用,而不能被其他包中的类使用,即使其他包中有该类的子类。这种访问特性又称为包访问性(package private //3 protected 用保护访问控制符 protected 修饰的类成员可以被三种类所访问:该类自身、与它在同一个包中的其他类以及在其他包中的该类的子类。使用 protected 修饰符的主要作用,是允许其他包中它的子类来访问父类的特定属性和方法,否则可以使用默认访问控制符。 //4 public 当一个类被声明为 public 时,它就具有了被其他包中的类访问的可能性,只要包中的其他类在程序中使用 import 语句引入 public 类,就可以访问和引用这个类

【7】静态变量和静态方法(static)

在类中,使用static修饰的变量是属于类的,正常类来调用,但是对象也可以调用

在类中,使用static修饰的方法是属于类的,正常类来调用,不需要实例化,就能调用,但是对象也可以调用,但是他的内部没有this关键字

什么情况下定义对象的方法[成员方法]

什么情况下定义类的方法[静态方法]

以后,不想初始化得到对象就能使用这个方法,就定义成静态方法。

(1)什么是静态变量(类变量)

  • 在类中,使用 static 修饰符修饰的属性(成员变量)称为静态变量,也可以称为类变量
    • 常量称为静态常量
    • 方法称为静态方法或类方法
  • 它们统称为静态成员,归整个类所有。
    • 静态成员不依赖于类的特定实例,被类的所有实例共享
    • 就是说 static 修饰的方法或者变量不需要依赖于对象来进行访问
    • 只要这个类被加载,Java 虚拟机就可以根据类名找到它们

(2)什么是静态变量

  • 类的成员变量可以分为以下两种:
    • 静态变量(或称为类变量),指被 static 修饰的成员变量
    • 实例变量,指没有被 static 修饰的成员变量
  • 静态变量与实例变量的区别如下:

  • 1)静态变量

    • 运行时,Java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配

    • 在类的内部,可以在任何方法内直接访问静态变量

    • 在其他类中,可以通过类名访问该类中的静态变量

  • 2)实例变量

    • 每创建一个实例,Java 虚拟机就会为实例变量分配一次内存

    • 在类的内部,可以在非静态方法中直接访问实例变量

    • 在本类的静态方法或其他类中则需要通过类的实例对象进行访问

(3)什么是静态方法

  • 类的成员方法也可以分为以下两种:
    • 静态方法(或称为类方法),指被 static 修饰的成员方法
    • 实例方法,指没有被 static 修饰的成员方法
  • 静态方法与实例方法的区别如下:
    • 静态方法不需要通过它所属的类的任何实例就可以被调用
    • 因此在静态方法中不能使用 this 关键字,也不能直接访问所属类的实例变量和实例方法
    • 但是可以直接访问所属类的静态变量和静态方法。
    • 另外和 this 关键字一样, super 关键字也与类的特定实例相关
    • 所以在静态方法中也不能使用 super 关键字
    • 在实例方法中可以直接访问所属类的静态变量、静态方法、实例变量和实例方法

【二】面向对象之继承

【1】继承格式

  • 在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

    class 父类 { } class 子类 extends 父类 { } class 子子类 extends 子类 { }
  • Java中的继承

    • 只支持单继承,不支持多继承,但支持实现多个接口
    • 支持一条线上的多重继承
  • Java不支持多继承,但是可以通过接口来实现多继承的功能

【2】构造方法

(1)分文件继承

  • 构造Animal类
public class Animal { String name; }
  • 构造Dog类
public class Dog extends Animal { int age; // 有参构造 public Dog(String name,int age){ this.name = name; this.age = age; } }
  • 实例化调用
public class Demo01 { public static void main(String[] args) { // 继承的关系测试 // 实例化得到一个DOG对象 // Dog = new Dog(); // 没有参数传入会报错,因为Dog内部是一个有参构造方法 Dog d = new Dog("dream", 18); System.out.println(d.name); // dream } }

(2)单文件继承

在一个文件中只能有一个 public 方法

class Animal { String name; } class Dog extends Animal { int age; // 有参构造 public Dog(String name,int age){ this.name = name; this.age = age; } } public class Demo01 { public static void main(String[] args) { // 继承的关系测试 // 实例化得到一个DOG对象 // Dog = new Dog(); // 没有参数传入会报错,因为Dog内部是一个有参构造方法 Dog d = new Dog("dream", 18); System.out.println(d.name); // dream } }

(3)小结

  • 子类如果没写构造方法
    • 默认使用父类无参构造
  • 本案例名字为:固定名字
// 1 子类如果没写构造方法,默认使用父类无参构造,本案例名字为:固定名字 // 2 子类如果没写构造方法,不会自动使用父类的有参构造,所以Person p=new Person("justin");用法是报错的
import java.util.*; public class Demo04 { public static void main(String[] args) throws Exception { Person p=new Person("justin"); p.Speak(); System.out.println(p.name); } } class Animal{ String name; public Animal(){ this.name="固定名字"; } public Animal(String name){ this.name=name; } public void Speak(){ System.out.println("动物说话"); } } class Person extends Animal { int age; // 子类如果没写构造方法,默认使用父类无参构造,本案例名字为:固定名字 // 子类如果没写构造方法,不会自动使用父类的有参构造,所以Person p=new Person("justin");用法是报错的 // public Person(String name,int age){ // this.name=name; // this.age=age; // } public void Run(){ System.out.println("人走路"); } @Override public void Speak(){ super.Speak(); // 代指父类对象,等同于python的super() System.out.println("人说话"); } }

【3】super 与 this 关键字

有了继承关系就会多了另一个关键字(原来有this):super(等同于python中的super())

  • super关键字:
    • 我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
  • this关键字:指向自己的引用
class Animal{ String name; public void Speak(){ System.out.println("动物说话"); } } class Person extends Animal { int age; public void Run(){ System.out.println("人走路"); } @Override public void Speak(){ this.Speak(); // 代指自己的,先从自己找,自己没有去父类找 super.Speak(); // 代指父类对象,等同于python的super(),直接去父类找 System.out.println("人说话"); } }

【三】重写(Override)与重载(Overload)

【1】什么是重写

  • 重写(Override)是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
  • 即外壳不变,核心重写

【2】什么是重载

  • 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。

  • 返回类型可以相同也可以不同

  • 被重载的方法必须改变参数列表(参数个数或类型不一样)

【3】演示

class Animal{ String name; public Animal(){ this.name="固定名字"; } public Animal(String name){ this.name=name; } public void Speak(){ System.out.println("动物说话"); } } class Person extends Animal { int age; public void Run(){ System.out.println("人走路"); } // 重载方法 - 方法名一样,参数不一样 public void Run(String ss){ System.out.println(ss); System.out.println("走路"); } // 重写方法Speak - 必须有继承关系 @Override public void Speak(){ super.Speak(); // 代指父类对象,等同于python的super() System.out.println("人说话"); } // 重载方法Speak public void Speak(String aa){ super.Speak(); // 代指父类对象,等同于python的super() System.out.println("人说话"); } }

【四】面向对象之接口

【1】接口的介绍

(1)接口是一个抽象类型

  • 接口(Interface),是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。
  • 一个类通过继承接口的方式,从而来继承接口的抽象方法。

只在接口中定义某个方法,可以不写这个方法,意思是继承接口的类必须要有我定义的接口中的方法

(2)接口并不是类

  • 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。
  • 类描述对象的属性和方法。接口则包含类要实现的方法。

(3)接口无法被实例化,但是可以被实现

  • 一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
  • 接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口不支持被 new

(4)接口与类相似点

  • 一个接口可以有多个方法
  • 接口文件保存在 .java 结尾的文件中,文件名使用接口名

(5)接口与类的区别

  • 接口不能用于实例化对象
  • 接口没有构造方法
  • 接口中所有的方法必须是抽象方法
  • 接口不能包含成员变量,除了 static 和 final 变量
  • 接口不是被类继承了,而是要被类实现
  • 接口支持多继承
    • 类可以实现多个接口

【2】接口声明

  • 定义接口语法
public interface 接口名 extends 其它接口 { // 声明变量 static 和 final 变量 // 声明方法,抽象方法 public Speak(); // 不用加{},这里只是定义了一个接口方法,而没有具体实现这个方法,所以不用加{} }
  • 官方一点的写法
[可见度] interface 接口名称 [extends 其他的接口名] { // 声明变量 // 抽象方法 }
  • 示例
  • 接口
interface Duck { //任何类型 final, static 字段 final String name="dream"; public static int age = 19; //抽象方法 public void Speak(); //public void Run(){}; // 不能有具体实现 public void Run(); // 不能有具体实现 }
  • 子类中实现接口
// 子类实现接口,必须实现接口中所有的方法 class TDuck implements Duck { @Override public void Speak() { System.out.println("鸭子叫"); } @Override public void Run() { System.out.println("鸭子走路"); } }
  • python中的鸭子类型
    • 只要我的方法中有这两个方法,就是同一类
class TDuck(): def speak(): pass def run(): pass class RDuck(): def speak(): pass def run(): pass
  • Java中的鸭子类型
    • 在Java中必须实现继承的同一个接口的两个类才叫鸭子类型,是同一类
interface Duck { //任何类型 final, static 字段 final String name = "dream"; public static int age = 19; //抽象方法 public void Speak(); //public void Run(){}; // 不能有具体实现 public void Run(); // 不能有具体实现 } // 子类实现接口,必须实现接口中所有的方法 class TDuck implements Duck { @Override public void Speak() { System.out.println("唐老鸭鸭子叫"); } @Override public void Run() { System.out.println("唐老鸭鸭子走路"); } } class RDuck implements Duck { @Override public void Speak() { System.out.println("肉鸭鸭子叫"); } @Override public void Run() { System.out.println("肉鸭鸭子走路"); } }

【3】接口继承

  • 可以继承多个接口
interface Duck { public void Speak(); public void Run(); } interface TDuck extends Duck{ public void Flay(); } // 接口的多继承:在Java中,类的多继承是不合法,但接口允许多继承。在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口 interface Foo extends Duck, TDuck{ }

【4】接口实现

  • 可以实现多个接口
// 实现接口,必须实现接口中所有的方法 interface Duck { //抽象方法 public void Speak(); public void Run(); // 不能有具体实现 } interface TDuck extends Duck{ public void Flay(); } class RealDuck implements TDuck{ @Override public void Speak() { } @Override public void Run() { } @Override public void Flay() { } }

【五】面向对象之抽象类

  • 定义格式
public abstract class Foo{ // 定义方法 public void Speak(){ System.out.println("Speak Speak Speak"); } // 定义抽象方法 public abstract void Sleep(); } // 继承 class Bird extends Foo { // Speak 已经有具体实现了,可以不重写 // 但是Sleep必须重写,因为没有实现 @Override public void Sleep() { System.out.println("必须重写抽象方法"); } }
  • 案例演示
public class Demo04 { public static void main(String[] args) { Bird b = new Bird(); b.Speak(); // Speak Speak Speak b.Sleep(); // 必须重写抽象方法 } } abstract class Foo { // 定义方法 public void Speak() { System.out.println("Speak Speak Speak"); } // 定义抽象方法 public abstract void Sleep(); } // 继承 class Bird extends Foo { // Speak 已经有具体实现了,可以不重写 // 但是Sleep必须重写,因为没有实现 @Override public void Sleep() { System.out.println("必须重写抽象方法"); } }

【六】抽象类和接口的区别

【小结】

  • 关键字不一样

  • 类继承是 implements extends

  • 类是类,接口是接口

  • 抽象类中方法可以具体实现,但是接口不能有具体实现

  • 一个类可以实现多个接口,但是不能继承多个类

【详解】

  • 关键字不同:

    • 在Java中,使用abstract关键字定义抽象类

    • 使用interface关键字定义接口。

  • 形式上的区别:

    • 类可以继承一个类,但类不能继承多个类

    • 一个类可以实现多个接口。

  • 方法的实现:

    • 抽象类可以包含具体的方法实现

      • 这些方法可以被子类继承和重写,也可以直接被调用。
    • 接口只能定义方法的签名

      • 不能包含方法的实现,实现接口的类必须提供接口中定义的所有方法的具体实现。
  • 字段的定义:

    • 抽象类可以定义实例变量

      • 这些变量可以是任意的访问修饰符,并且可以有默认值。
    • 接口只能定义常量字段(static final

      • 而且字段默认为公共、静态和最终。
  • 设计思想:

    • 抽象类用于表示一种通用的父类

      • 其中包含了子类所共有的属性和方法。
    • 接口则用于定义一组行为和功能的规范

      • 不关心具体实现细节,只关注方法的输入和输出。
  • 总结来说
    • 抽象类更类似于普通类的扩展和继承
    • 接口更像是一种规范或者契约,用于描述类应该具有的行为和功能。
  • 在设计中,应根据具体的需求选择使用抽象类还是接口。
    • 如果需要表达一种"is-a"的关系并且需要共享代码实现
      • 可以使用抽象类;
    • 如果需要表达一种"has-a"的关系或者需要多继承
      • 可以使用接口。

【七】面向对象之封装

【1】面向对象三大特性

  • 继承

  • 多态

  • 封装

  • 封装

    • 把属性或方法放在类的内部,可以隐藏起来,然后拿到一个对象
    • 可以 .属性 .方法 进行使用

【2】在Java中,习惯把属性定义成私有的,然后提供方法,来进行读写

public class Demo05 { public static void main(String[] args) { // 实例化类对象 Fish f = new Fish(); f.name = "xxx"; // 这样做是不行的,因为类属性被定义为私有的属性,无法通过实例化对象调用去修改私有属性 } } // 定义一个类 class Fish { // 类里面放了一个私有属性 private String name; }
  • 解决
public class Demo05 { public static void main(String[] args) { // 实例化类对象 Fish f = new Fish(); // 通过方法去修改设置属性 - 安全 f.setName("小黄鱼"); System.out.println(f.getName()); // 小黄鱼 } } // 定义一个类 class Fish { // 类里面放了一个私有属性 private String name; // Java 中习惯这样用 // 开放接口方法,供外部修改调用 public void setName(String name) { this.name = name; } // 开放接口方法,当外部访问时,可以将想要反出去内容返回 public String getName() { return this.name; } }
  • 支持自定义返回数据
public class Demo05 { public static void main(String[] args) { // 实例化类对象 Fish f = new Fish(); // 通过方法去修改设置属性 - 安全 f.setName("小黄鱼"); System.out.println(f.getName()); // 小黄鱼安全属性 } } // 定义一个类 class Fish { // 类里面放了一个私有属性 private String name; // Java 中习惯这样用 // 开放接口方法,供外部修改调用 public void setName(String name) { this.name = name; } // 开放接口方法,当外部访问时,可以将想要反出去内容返回 public String getName() { // 支持返回的数据拼接其他的东西 return this.name + "安全属性"; } }

【3】详解

// java中一般不直接通过对象调用属性,而是通过方法来设置和获取属性【更安全】 class Person { public String name ; private int age; public void setAge(int age){ this.age=age; } public int getAge(){ return this.age+1; } }

【八】面向对象之多态

【1】什么是多态

  • 多态是同一类事物[实例,对象]多种形态
猫对象1狗对象1都属于动物类 --> 动物类(通过继承,实现多个接口),有多种具体形态 调用 同一类事物共有的方法 --> 虽然调用同样的方法,但是各自表现出来的不一样,狗是狗叫,猫是猫叫
  • 从而调用同一类[实例,对象]方法时,表现出不同

【2】多态存在的三个必要条件

  • (1)编写具有继承关系的父类和子类/接口实现
  • (2)子类重写父类方法
  • (3)使用父类的引用指向子类的对象
前面是父类 ---- 指向了具体的某一个类 Duck d = new Tduck() 而不是 Tduck d = new Tduck()

【3】继承实现的多态

public class Demo06 { public static void main(String[] args) { // 多态 // 实例化得到对象 // 将具体的类赋值给父类 Foo1 c1 = new Child1(); Foo1 c2 = new Child2(); // 调用方法 c2.Run(); c2.Speak(); // c2.Sleep(); // c2是Foo1类型,Foo1没有 Sleep 方法,所以不能调用 Sleep 方法 // 如果想调用必须要做类型转换 Child2 cc2 = (Child2) c2; // 强制转换数据类型 cc2.Sleep(); // 转成具体类型,可以调用具体的独有的方法 // c1 可以转换成 Child2 类型吗? // 不可以,每个对象有每个对象自己独有的类,不能将两个本质上不同的类强转成另一个类 // 即 c1 本质上是 Child1 类型 , 不能强转成 Child2 类型 // 强转类型建议加 If 判断 if (c1 instanceof Child1) { Child1 cc1 = (Child1) c1; } } } // 定义父类 class Foo1 { public void Speak() { System.out.println("父类的Speak方法"); } public void Run() { System.out.println("父类的Run方法"); } } // 子类继承父类 class Child1 extends Foo1 { // 重写父类方法可以不写 @Override public void Speak() { System.out.println("这是子类1中重写的 Speak 方法"); } @Override public void Run() { System.out.println("这是子类1中重写的 Run 方法"); } } class Child2 extends Foo1 { // 重写父类方法可以不写 @Override public void Speak() { System.out.println("这是子类2中重写的 Speak 方法"); } @Override public void Run() { System.out.println("这是子类2中重写的 Run 方法"); } // 定义子类独有的方法 public void Sleep() { // 派生方法: 比父类方法多的方法叫派生方法 System.out.println("这是子类2独有的 Sleep 方法"); } }
  • 子类转父类不叫强转,直接赋值给父类即可
  • 父类转子类需要强转,强转可能会出错

【4】其他知识详解

(1)多态成员变量编译运行看左边

public class Demo04 { public static void main(String[] args) throws Exception { // 1 多态成员变量:编译运行看左边 Animal dog = new Dog(); System.out.println(dog.age); } } //父类 class Animal { public int age = 11; } //子类 class Dog extends Animal { public int age = 33; }

(2)多态成员方法:编译看左边,运行看右边

public class Demo04 { public static void main(String[] args) throws Exception { // 1 多态成员变量:编译运行看左边 Animal dog = new Dog(); System.out.println(dog.age); // 2 多态成员方法:编译看左边,运行看右边 dog.eat(); } } //父类 class Animal { public int age = 11; public void eat() { System.out.println("动物吃饭"); } } //子类 class Dog extends Animal { public int age = 33; @Override public void eat() { System.out.println("狗吃饭"); } }

(3)子类增加独有方法walk()

import java.util.*; import com.justin.*; import com.justin.Db; import com.justin.Helper; public class Demo04 { public static void main(String[] args) throws Exception { // 1 多态成员变量:编译运行看左边 Animal dog = new Dog(); System.out.println(dog.age); // 2 多态成员方法:编译看左边,运行看右边 dog.eat(); // 3 无法调用子类独有方法 //dog.walk(); } } //父类 class Animal { public int age = 11; public void eat() { System.out.println("动物吃饭"); } } //子类 class Dog extends Animal { public int age = 33; @Override public void eat() { System.out.println("狗吃饭"); } public void walk() { System.out.println("狗走路"); } }

(4)引用类型转换

  • 1 向上转型:【儿子变父亲】
    • 多态本身是子类向父类向上转换(自动转换)的过程
    • 这个过程是默许的
    • 当父类引用指向一个子类对象时,就是向上转型
  • 2 向下转型:【父亲变儿子,需要强制转换】
    • 向下转型,强制类型转换
Dog dog1 = (Dog) dog; dog1.walk();
  • 3 类型转换会出现【类型转换异常】
  • 4 instanceof 判断具体类型
import java.util.*; import com.justin.*; import com.justin.Db; import com.justin.Helper; public class Demo04 { public static void main(String[] args) throws Exception { // 强制类型转换会出错 Animal cat = new Cat(); // Dog d=(Dog)cat; // d.walk(); // 通过instance判断再转 if(cat instanceof Cat){ Cat c=(Cat) cat; c.sleep(); } } } //父类 class Animal { public int age = 11; public void eat() { System.out.println("动物吃饭"); } } //子类 class Dog extends Animal { public int age = 33; @Override public void eat() { System.out.println("狗吃饭"); } public void walk() { System.out.println("狗走路"); } } class Cat extends Animal { public int age = 63; @Override public void eat() { System.out.println("猫吃饭"); } public void sleep() { System.out.println("猫睡觉"); } }

(5)抽象类实现的多态

public class Demo04 { public static void main(String[] args) throws Exception { // 抽象类实现的多态 Animal a=new Dog(); a.eat(); a.speak(); } } //父类 abstract class Animal { abstract void speak(); public void eat() { System.out.println("动物吃饭"); } } //子类 class Dog extends Animal{ // 必须重写虚类上的方法 @Override void speak() { System.out.println("狗叫"); } }

(6)接口实现的多态

import java.util.*; import com.justin.*; import com.justin.Db; import com.justin.Helper; public class Demo04 { public static void main(String[] args) throws Exception { // 2 接口实现的多态 Animal a=new Dog(); a.speak(); } } interface Animal { public void speak(); } //子类 class Dog implements Animal{ @Override public void speak() { System.out.println("狗叫"); } public void eat() { System.out.println("狗吃"); } }

【九】枚举

  • Java 枚举是一个特殊的类,一般表示一组常量,
    • 一年的 4 个季节
    • 一年的 12 个月份
    • 性别有男,女,未知
import java.util.*; public class Demo04 { public static void main(String[] args) throws Exception { // 1 简单使用 System.out.println(Sex.Unknown); System.out.println(Sex.Male); // 2 更多使用 System.out.println("枚举顺序值,"+Week.SUNDAY.ordinal()); // 0 System.out.println(Week.MONDAY.id); System.out.println(Week.MONDAY.meaning); } } enum Sex { Male, Female, Unknown; } enum Week { SUNDAY(0, "星期日"), MONDAY(1, "星期一"), TUESDAY(2, "星期二"), WEDNESDAY(3, "星期三"), THURSDAY(4, "星期四"), FRIDAY(5, "星期五"), SATURDAY(6, "星期六"); public int id; public String meaning; Week(int id, String meaning) { this.id = id; this.meaning = meaning; } }

【十】包(package)

【1】什么是包

  • 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。

我们可以定义很多包

不同包下,类名可以重复

同一个包下,类名不能重复

【2】包的作用

  • 1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用

  • 2、同文件夹一样,包采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。

  • 3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

【3】创建包

// 右键,新建包----》其实就是文件夹 com.dream // 在包中定义类 com.dream Db.java Helper.java
  • Helper.java
// 先声明是哪个包下的类(功能) package com.dream; public class Helper { public int add(int a ,int b){ return a+b; } }

【4】引入包,并使用包中的类

// 导入包下的所有类 import com.dream.*; // 单独导入指定的包 import com.dream.Db; import com.dream.Helper; public class Demo04 { public static void main(String[] args) throws Exception { // 实例化的到dream类 Helper h=new Helper(); System.out.println(h.add(4,5)); } }

__EOF__

本文作者Chimengmeng
本文链接https://www.cnblogs.com/dream-ze/p/17557889.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Chimengmeng  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示