day07-java基础3

发布时间 2023-10-17 16:04:41作者: hanfe1

一 面向对象之类与对象

1.1 类与对象

# 类:
  类是实体对象的概念模型,是笼统的、不具体的,比如人类,动物类,鸟类
  类是描述了一组有相同特性(属性)和相同行为(方法)的一组对象的集合
# 对象:
	对象又称为【实体】,是类具体化的表现,如人类中有:厨师,学生,老师
  每个人对象都具有:姓名、年龄和体重这些属性,但是每个对象的姓名年龄又不相同
  每个对象都具有:说话,走路的方法

1.1.1 类定义规范

// []内可以省略,|表示或单两个关键字不能同时出现
[public] [abstract|final] class 类名class_name [extends 继承的类名] [implements 实现的接口名] {
    // 定义成员属性
		属性类型1 属性名1;  // String name; 
  	属性类型2 属性名2;  // int age; 
    // 定义静态属性(类属性)
  
    // 定义成员方法
    public int add(int a,int b){
        return a+b;
    }
  	// 定义静态方法(类方法)
   public static void speak(){
        System.out.println("说话");
    }
  
}

// 解释
public :表示 共有 的意思。如果使用 public 修饰,则可以被其他类和程序访问。每个 Java 程序的主类都必须是 public 类,作为公共工具供其他类和程序使用的类应定义为 public 类
  
abstract :类被 abstract 修饰,则该类为抽象类,抽象类不能被实例化,但抽象类中可以有抽象方法(使用 abstract 修饰的方法)和具体方法(没有使用 abstract 修饰的方法)。继承该抽象类的所有子类都必须实现该抽象类中的所有抽象方法(除非子类也是抽象类)
  
final :如果类被 final 修饰,则不允许被继承
  
class :声明类的关键字
  
class_name :类的名称
  
extends :表示继承其他类

implements :表示实现某些接口

1.1.2 Java类的属性

// 语法
[public|protected|private] [static][final] <变量类型> <变量名>
// 解释
public protected private :用于表示成员变量的访问权限
static :表示该成员变量为类变量,也称为静态变量
final :表示将该成员变量声明为常量,其值无法更改 
变量类型 :表示变量的类型
变量名:表示变量名称
  
// 例如
public class Person {
    public String name;    // 姓名
    final int sex = 0;    // 性别:0表示女孩,1表示男孩
    private int age;    // 年龄
}

1.1.3 创建一个类

//1   定义一个Person类
public class Person {
    // 属性
    public String Name;    // 姓名
    public int Age;    // 年龄
    private boolean Sex;    // 性别

    // 方法
    public boolean isSex() {
        return this.Sex;
    }
    public void setSex(boolean sex) {
        this.Sex = sex;
    }
}

//2 使用Person类
public class Demo04 {
    public static void main(String[] args) throws Exception {
        Person p=new Person();
        p.setSex(true);
        System.out.println(p.isSex());
    }
}

1.1.4 成员方法

// 语法
[public|private|protected] [abstract] [static]  <void|return_type><方法名>([参数]) {
        // 方法体
}

// 解释
public private protected :表示成员方法的访问权限
static :表示限定该成员方法为静态方法
final :表示限定该成员方法不能被重写或重载
abstract :表示限定该成员方法为抽象方法。抽象方法不提供具体的实现,并且所属类型必须为抽象类
  

1.1.5 构造方法

// 构造方法与类同名,没有返回值,不需要void关键字,可以有多个,表示多种构造方式
public class Bird {
    String name;
    int age;
    public Bird() {
    }
    public Bird(String name, int age) {
        this.age = age;
        this.name = name;
    }
}

1.1.6 this关键字

// this在类内部使用,代指当前实例[对象],等同于python的self
public class Bird {
    String name;
    int age;

    public Bird() {

    }

    public Bird(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public int add(int a, int b) {
        return a + b;
    }

    public void Speak() {
        System.out.println(this.add(9, 8));
        System.out.print(this.name);
        System.out.print("说话了\n");
    }

}

1.1.7 访问控制修饰符

访问范围 private friendly(默认) protected public
同一个类 可访问 可访问 可访问 可访问
同一包中的其他类 不可访问 可访问 可访问 可访问
不同包中的子类 不可访问 不可访问 可访问 可访问
不同包中的非子类 不可访问 不可访问 不可访问 可访问
//1  private
用 private 修饰的类成员,只能被该类自身的方法访问和修改,而不能被任何其他类(包括该类的子类)访问和引用。因此,private 修饰符具有最高的保护级别
  
//2 friendly(默认)
如果一个类没有访问控制符,说明它具有默认的访问控制特性。这种默认的访问控制权规定,该类只能被同一个包中的类访问和引用,而不能被其他包中的类使用,即使其他包中有该类的子类。这种访问特性又称为包访问性(package private)

//3  protected
用保护访问控制符 protected 修饰的类成员可以被三种类所访问:该类自身、与它在同一个包中的其他类以及在其他包中的该类的子类。使用 protected 修饰符的主要作用,是允许其他包中它的子类来访问父类的特定属性和方法,否则可以使用默认访问控制符。
  
//4 public
当一个类被声明为 public 时,它就具有了被其他包中的类访问的可能性,只要包中的其他类在程序中使用 import 语句引入 public 类,就可以访问和引用这个类

1.1.8 静态变量和静态方法(static)

// 在类中,使用 static 修饰符修饰的属性(成员变量)称为静态变量,也可以称为类变量,常量称为静态常量,方法称为静态方法或类方法,它们统称为静态成员,归整个类所有。

// 静态成员不依赖于类的特定实例,被类的所有实例共享,就是说 static 修饰的方法或者变量不需要依赖于对象来进行访问,只要这个类被加载,Java 虚拟机就可以根据类名找到它们

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

// 静态变量与实例变量的区别如下:
1)静态变量
运行时,Java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配
在类的内部,可以在任何方法内直接访问静态变量
在其他类中,可以通过类名访问该类中的静态变量

2)实例变量
每创建一个实例,Java 虚拟机就会为实例变量分配一次内存
在类的内部,可以在非静态方法中直接访问实例变量
在本类的静态方法或其他类中则需要通过类的实例对象进行访问

//********************静态方法********************
类的成员方法也可以分为以下两种:
静态方法(或称为类方法),指被 static 修饰的成员方法
实例方法,指没有被 static 修饰的成员方法

  
// 静态方法与实例方法的区别如下:
静态方法不需要通过它所属的类的任何实例就可以被调用,因此在静态方法中不能使用 this 关键字,也不能直接访问所属类的实例变量和实例方法,但是可以直接访问所属类的静态变量和静态方法。另外和 this 关键字一样, super 关键字也与类的特定实例相关,所以在静态方法中也不能使用 super 关键字
在实例方法中可以直接访问所属类的静态变量、静态方法、实例变量和实例方法

二 面向对象之继承

2.1 继承格式

// 在 Java 中通过 extends 关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:
// Java中的继承,只支持单继承,不支持多继承,但支持实现多个接口

class 父类 {
}
 
class 子类 extends 父类 {
}
class 子子类 extends 子类 {
}

image-20231017153411114

2.2 构造方法

1 子类如果没写构造方法,默认使用父类无参构造,本案例名字为:固定名字

// 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("人说话");

    }
}

2.3 super 与 this 关键字

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(){
        super.Speak(); // 代指父类对象,等同于python的super()
        System.out.println("人说话");

    }
}

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

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

// 2 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同
	被重载的方法必须改变参数列表(参数个数或类型不一样)
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 接口(Interface),是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过实现接口的方法,从而来实现接口的抽象方法。

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

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

4 接口与类相似点:
  一个接口可以有多个方法
  接口文件保存在 .java 结尾的文件中,文件名使用接口名
  
5 接口与类的区别:
  接口不能用于实例化对象
  接口没有构造方法
  接口中所有的方法必须是抽象方法
  接口不能包含成员变量,除了 static 和 final 变量
  接口不是被类继承了,而是要被类实现
  接口支持多继承
  
  

4.1 接口声明

[可见度] interface 接口名称 [extends 其他的接口名] {
        // 声明变量
        // 抽象方法
}

interface Duck {
    //任何类型 final, static 字段
    final String name="justin";
    public static int age = 19;

    //抽象方法
    public void Speak();
    //public void Run(){}; // 不能有具体实现
    public void Run(); // 不能有具体实现
}

4.2 接口继承

interface Duck {
    public void Speak();
    public void Run();
}

interface TDuck extends Duck{
    public void Flay();
}

// 接口的多继承:在Java中,类的多继承是不合法,但接口允许多继承。在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口
interface Foo extends Duck, TDuck{
}

4.3 接口实现

// 实现接口,必须实现接口中所有的方法
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() {

    }
}

五 面向对象之抽象类

import java.util.*;

public class Demo04 {
    public static void main(String[] args) throws Exception {

        Bird b=new Bird();
        b.Speak();
        b.Run();

    }

}

abstract class Animal{
    public abstract void Speak();
    public void Run(){
        System.out.println("run run run");
    }

}

class Bird extends Animal{

    // 虚拟类的虚拟方法必须被重写
    @Override
    public void Speak() {
        System.out.println("说话");
    }
}


六 封装

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

image-20231017153510257

七 多态

// ***********多态解释**********************
// 多态是同一类事物[实例,对象]多种形态,从而调用同一类[实例,对象]方法时,表现出不同


// **********************多态存在的三个必要条件**********************
  (1)编写具有继承关系的父类和子类
  (2)子类重写父类方法
  (3)使用父类的引用指向子类的对象

7.1 继承实现的多态

7.1.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;

}

7.1.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("狗吃饭");
    }
}

7.1.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("狗走路");
    }

}

7.1.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("猫睡觉");
    }

}

7.2 抽象类实现的多态


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("狗叫");
    }
}

7.3 接口实现的多态

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)

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

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

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

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

9.1 创建包

// 右键,新建包----》其实就是文件夹
	com.justin
 
// 在包中定义类
com.justin
	Db.java
	Helper.java

// Helper.java
package com.justin;
public class Helper {
    public int add(int a ,int b){
        return a+b;

    }
}
    

9.2 引入包,并使用包中的类

import com.justin.*;
import com.justin.Db;
import com.justin.Helper;

public class Demo04 {
    public static void main(String[] args) throws Exception {
        Helper h=new Helper();
        System.out.println(h.add(4,5));
    }
}