Java面向对象【笔记】

本文详细介绍了面向对象编程中的关键概念,包括类和对象的关系、创建类与对象的方式、封装属性和行为、构造方法的使用、权限修饰符、继承机制、super关键字、方法重写、final关键字、包的概念、Object类特性以及抽象与接口的定义。还涵盖了多态的原理和应用,以及内部类特别是匿名内部类的用法。
摘要由CSDN通过智能技术生成

面向对象

1、类和对象

类:某一类相同事物的抽象描述(公共的属性/行为)

对象 :类中的具体实例(类的对象/类的实例)

**关系:**编程语言中,先有类,根据类创建对象

2、创建类

public class 类名{
    //公共的属性  行为
    
}

3、创建对象

格式:

new 类名();//创建某个类的对象

new:创建对象

注意:

​ 为了更加方便的操作对象,一般会定义变量指向对象

数据类型 变量名 = new 类名();

每个类都是一种数据类型(引用类型)

对象创建好以后,会有类中的属性和行为

4、访问属性和行为

格式

对象.属性//成员变量:类的里面,方法外面定义的变量
对象.行为//成员方法
    
    std.xh//变量
    std.eat()//方法

注意:

​ 属性是没有()

​ 行为有()

5、对象的初始化

给对象的属性赋值

对象.属性=;

std.xh =;

6、重写toString方法

可以定义查看的内容

封装

1、构造方法

给对象的属性进行初始化

格式:

public 类名(参数列表){
    //给类的(对象)属性初始化
}

注意:

  • ​ 构造方法没有返回值

  • ​ 方法名必须和类名保持一致

  • ​ 构造方法写在初始化属性所在的类中

  • ​ 构造方法可以有多个

  • ​ 构造方法不能手动调用

  • ​ 创建对象的时候会自动调用构造方法

  • ​ 在创建对象的时候给构造方法的参数进行传参

class Student{
    int xh;
    String name;
    String gender;
    int age;
//构造方法:无参构造(不会给属性初始化)
	public Student(){
	}
//构造方法:给所有属性都进行初始化
	public Student(int xh,String name,String gender,int age){//规范:参数名和属性名保持一致
    	this.xh = xh;//this.xh访问的是成员变量
        this.name = name;//this.name
        this.gender = gender;//this.gender赋值给gender
        this.age = age;//this.age赋值给age
	}
}

如果在方法中,出现了同名的局部变量和成员变量,在方法中默认访问的是局部变量,可以通过this关键字访问成员变量

格式:
    this.变量

问题:为什么以前不写无参构造,也可以创建?

解答:如果没有手动去写构造方法,JVM会自动创建无参构造

​ 如果手动写构造方法,JVM不会创建无参构造方法

2、封装

​ 封装实体类的属性

实体类:

​ 封装数据的类

工具类:

​ 写工具方法

测试类:

​ 测试代码

封装的格式:

​ 第一步:私有化成员变量(属性)

​ private 数据类型 变量名;

​ 第二步:成员变量提供公共的set/get方法

public class Book{
   	private String name;
	//set方法:设置属性值 
	public void setName(String name){//设置
    //过滤代码
   	 	this.name = name;
	}
	//get方法:获取值
	public void getName(){//获取
   	 	return name;
	}
}

规范:没有特殊要求,实体类的属性都要进行封装

3、权限修饰符(访问控制符)

​ 控制类中的成员,能否被其它地方访问到

​ 从大到小:

​ public protected default private

public:公共的,任意位置访问

protected:

default:

private:私有的,只有当前类可以访问

实际案例:超市后台管理系统

Market_Sys

package example2;

import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.util.Scanner;

public class Market_Sys {
    //创建Scanner对象
    private static Scanner scanner = new Scanner(System.in);
    //创建数组,保存会员信息
    private static Member[] members = new Member[100];
    //定义变量,保存索引值
    private static int index = 0;//保存数据的索引值
    //显示主页
    public static void showMain(){
        System.out.println("购物管理系统 > 会员信息管理");
        System.out.println("**********************************");
        System.out.println("1. 添加会员信息");
        System.out.println("2. 修改会员信息");
        System.out.println("3. 查询会员信息");
        System.out.println("4. 显示所有会员信息");
        System.out.println("5. 退出系统");
        System.out.println("**********************************");
    }

    //添加会员信息
    public static void addVIP(){
        System.out.println("===添加会员信息===");
        System.out.println("请输入会员卡号:");
        //录入会员卡号
        String num = scanner.next();
        System.out.println("请输入会员生日(月/日<用两位数表示>):");
        //录入生日
        String birthday = scanner.next();
        System.out.println("请输入积分:");
        //录入积分
        String score = scanner.next();
        //录入会员信息,保存起来 :实体类+数组
        //创建Memeber对象
        Member member = new Member();
        //把录入的数据保存到member对象中
        member.setNum(num);
        member.setBirthday(birthday);
        member.setScore(Integer.parseInt(score));
        //把会员保存到数组中
        members[index] = member;
        index ++;
        System.out.println("添加会员信息成功!");
    }

    //修改会员
    public static void updateVIP(){
        System.out.println("===修改会员信息===");
        System.out.println("请输入会员卡号:");
        //录入输入的卡号
        String num = scanner.next();

        System.out.println("*********************************");
        System.out.println("1 修改会员生日");
        System.out.println("2 修改会员积分");
        System.out.println("*********************************");
        //录入选择
        String option = scanner.next();
        switch (option){
            case "1":
                //修改生日
                update(num,1);
                break;
            case "2":
                //修改会员积分
                update(num,2);
                break;
            default:
                System.out.println("选择有无!");
                break;
        }
        System.out.println();
    }
    //方法:修改用户信息
    //num:卡号(要修改哪个用户)   option:修改内容  1:修改生日/2:修改积分
    public static void update(String num,int option){
        //遍历所有会员
        for (int i = 0; i < index; i++) {
            //当前会员: members[i]
            Member member = members[i];
            //判断当前会员是不是用户指定要修改的会员
            if(member.getNum().equals(num)){
                //判断修改什么内容
                if(option==1){
                    //修改生日
                    System.out.println("请输入修改后的生日:");
                    //录入新的生日
                    String newBirthday = scanner.next();
                    //修改当前会员生日
                    member.setBirthday(newBirthday);
                    System.out.println("生日修改成功");
                }else if(option==2){
                    //修改积分
                    System.out.println("请输入修改后的积分:");
                    //录入新的积分
                    String newScore = scanner.next();
                    //修改当前会员积分
                    member.setScore(Integer.parseInt(newScore));
                    System.out.println("积分修改成功");
                }
                return ;//结束函数,不需要再继续循环判断
            }
        }
        //卡号不存在
        System.out.println("卡号不存在");
    }


    //查询会员
    public static void findVIP(){
        System.out.println("===查询会员信息===");
        System.out.println("请输入会员卡号:");
        //录入会员卡号
        String num = scanner.next();//用户想要查询的卡号

        //根据卡号,从members找会员信息
        //遍历数组:根据索引值index遍历(假设数组只保存了5个数据,有必有遍历100个数据?)
        boolean flag = false;//假设没有
        for (int i = 0; i < index; i++) {
            //当前member对象
            Member member = members[i];
            //判断当前这个member对象是我们要的对象吗?
            //根据卡号判断
            if(member.getNum().equals(num)){//当前会员卡号 和  录入的卡号比较   ==:基本类型/引用类型  String:引用类型
                //如果相同,代表找到了
                flag = true;
                //显示头信息
                System.out.println("会员号\t生日\t积分");
                System.out.println(member.getNum()+"\t"+member.getBirthday()+"\t"+member.getScore());
                break;
            }
        }
        if(flag==false){
            //没找到
            System.out.println("会员号不存在!");
        }
        System.out.println();
    }

    //显示所有会员
    public static void findAllVIP(){
        System.out.println("===显示所有会员===");
        if(index==0){
            System.out.println("没有任何数据!");
        }else{
            //显示头信息
            System.out.println("会员号\t生日\t积分");
            for (int i = 0; i < index; i++) {
                Member member = members[i];
                System.out.println(member.getNum()+"\t"+member.getBirthday()+"\t"+member.getScore());
            }
        }
        System.out.println();
    }

    //程序主入口
    public static void main(String[] args) {//主函数有static,在主函数中去访问其它成员,其它成员必须有static
        while(true){
            //显示主页
            showMain();
            //获取用户的选项(键盘录入的数据):Scanner对象
            //提示信息:
            System.out.println("请输入数字(1-4):");
            //调用方法获取录入的数据
            String option = scanner.next();//返回的字符串
//        System.out.println("录入的数据是:"+option);
            //判断用户录入的内容
            switch (option){
                case "1":
                    //添加会员信息
                    addVIP();
                    break;
                case "2":
                    //修改会员信息
                    updateVIP();
                    break;
                case "3":
                    //查询会员信息
                    findVIP();
                    break;
                case "4":
                    //显示所有会员信息
                    findAllVIP();
                    break;
                case "5":
                    //显示所有会员信息
                    System.exit(0);//结束程序
                    break;
                default:
                    System.out.println("选项有误,请重新选择:");
                    break;
            }
        }
    }
}

Member

package example2;
//封装会员信息
public class Member {
    private String num;//卡号
    private String birthday;//生日
    private int score;//积分

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Member{" +
                "num='" + num + '\'' +
                ", birthday='" + birthday + '\'' +
                ", score=" + score +
                '}';
    }
}

继承

1、static关键字

​ static:静态

用在属性上:

​ 静态成员变量,在内存中只有一份,是共享数据

访问方式:

​ 类名.静态属性

​ 对象.静态属性(不推荐使用)

常量:

public static final int NUM = 123;

静态方法:

一般用在工具类中

public static void main(String[] args)

访问方式:

​ 对象.方法名()

​ 类名.方法名()(推荐使用)

注意:

​ 静态方法只能访问静态成员

代码块

​ 静态代码块

static{
    
}

特点:静态代码块的内容只会在加载类的时候执行一次

对比非静态代码块:

{}

特点:每次创建对象都会执行一次

2、继承

继承:

​ 类与类之间的一种关系

关键字:

​ extends

格式

public class 类名1 extends 类名2{
    
}
//类名1:子类
//类名2:父类

单继承:

​ 子类只能有一个直接父类

特点:

​ 子类继承父类后,可以去使用父类的属性和行为

注意:

​ 父类私有成员的不能继承

​ 父类的构造方法不能继承,但是可以在子类中调用父类的构造方法(子类会默认调用父类的无参构造方法)

3、super关键字

​ 父类空间引用

1、调用父类的构造方法:给父类构造方法初始化

   super(实参列表);//调用父类无参构造
   super(name ,color,weight);//调用父类3个参数的构造函数

注意

​ super调用构造方法时,只能位于第一个语句

2、获取父类的属性

super.属性名;

问题:父类中的toString()方法,不能满足子类的需求

4、方法的重写

使用:

​ 父类方法无法满足子类需求,可以在子类中重写该方法

格式:

​ 方法名和参数列表一致

前提:

​ 一定要有继承(或实现)关系

对比方法的重载:

​ 方法名相同,参数列表不同

​ 在同一个类中,不需要继承关系

5、final关键字

​ final:最终的

1、修饰类

​ 类不能被继承

2、修饰方法

​ 方法不能被重写

3、修饰属性(变量)

​ 变量不能重新赋值

4、常量

public static final int NUMBER = 1;

注意:常量全部大写

6、包的概念

​ 文件夹

不同包中的内容如何访问:

​ 导包

package //声明包,指定当前文件所在包
package test1;//当前类在test1包中
package test2;//当前类在test2包中
import //包名.类名;
import test1;//把test1包导入
import test1.person;//把test1包中的person类导入
import test1.*;//把test1包中的全部类导入
//*通配符,所有内容

注意:

​ 包名全部小写

同包中的内容如何访问:

7、Object类

Object类是所有类的父类

常用方法
1、equals()方法

​ 比较内存地址

注意:如果子类没有重写equals()方法,默认都是比较内存地址

思考:在比较字符串(String)时,为什么可以直接用equals()比较字符串内容?

原因:

​ String重写了equals()方法,在String的equals()方法中比较的是字符串内容

2、toString()方法

​ 获取对象的字符串(以字符串的形式表示对象)

​ 实体类中一般会重写toString方法

3、hashCode()方法

​ 获取对象的哈希值(以数字的形式表示对象)

4、getClass()方法

​ 获取运行时的一个类

注意:所有的子类如果没有去重写equals()方法,默认都比较内存地址,如果子类想要修改比较规整,就要重写equals()方法

抽象与接口

1、抽象

关键字:

​ abstract

抽象类:用abstract修饰的类

public abstract class 类名{}

抽象方法:用abstract修饰的方法

修饰符 abstract 返回值类型 方法名();

注意:

  • 抽象方法没有方法体
  • 一个类中如果有抽象方法体,这个类必须是抽象类
  • static和abstract不能一起用:static修饰方法后,方法可以通过类名访问
  • 抽象方法不能调用
  • 如果父类中有抽象方法,子类一定要重写
  • 抽象类中可以有抽象方法,也可以没有
  • 抽象类不能创建对象
  • 抽象类就是给子类继承用的

作用:要求子类强制重写

2、接口

​ 更加彻底的抽象,接口中都是抽象方法(定义规范)

作用:

​ 解耦,降低代码耦合性

接口关键字

​ interface

格式

public interface 接口名{
    //抽象方法
}

注意:

​ 接口不能创建对象

使用接口:

​ 创建接口实现类

实现:

​ 类与接口之间的关系

对比继承:

​ 继承(类于类之间)

实现关键字:

​ implements

public class 类名 implements 接口名{
    
}

注意:

  • 一个类实现了接口,就要实现(重写)接口中的抽象方法
  • 接口中的修饰符可以不写,默认是public,可以省略
  • 一个类实现接口的同时可以继承另外一个类。(先继承再实现)
public class 类名 extends 父类 implements 接口1,implements 接口2{
    
}
  • 一个接口可以有多个实现类

接口与接口之间的关系:继承

注意:接口之间的继承是多继承,类于类之间是单继承

Day14多态

简单理解: 一个对象可以有多个形态

例如:父类:Animal

​ 子类:Cat Dog Pig

​ 定义父类型变量Animal a;//变量a可能是Cat/Dog/Pig

注意:多态只有在运行的时候才能知道具体是谁

多态的体现:

父类的引用类型变量执行子类对象

接口的引用类型变量指向接口实现类对象

例如:

Animal cat = new Cat();
//Animal cat:父类的变量
//new Cat():创建子类对象

1、父类型变量指向子类对象

多态的使用前提:

​ 必须存在继承或者实现关系

注意:

  • 在多态情况下,访问的是父类成员,不能访问子类特有成员

  • 在多态情况下,如果子类和父类存在同名的属性,访问的是父类属性

  • 在多态情况下,如果子类和父类存在同名的非静态方法,访问的是子类方法

  • 在多态情况下,如果子类和父类存在同名的静态方法,访问的是父类方法

使用:

​ 用在参数列表中,可以接收更多类型的参数(所有子类型数据)

如何判断多态的具体类型:

​ instanceof关键字

对象 instanceof 类名
    //判断对象是否属于某个类型

//测试类
public static void showMsg(Animal aniaml){
    if(animal instanceof Cat){
       	Cat cat = (Cat)animal;
        System.out.println(cat.age);
        System.out.println("我是cat,我爱老鼠");
    }else if(animal instanceof Dog){
        Dog dog = (Dog)animal;
        System.out.println("我是Dog,我爱猫咪");
    }else if(animal instanceof Pig){
        Pig pig = (Pig)animal;
        System.out.println("我是pig,我爱睡觉");
    }
 }
//实体类Animal
public String name;
public String color;
//实体类Cat
public String age;

概念:

​ 向上转型(自动):

Animal cat = new Cat();

​ 向下转型(强制转换):

​ 一般先使用instanceof进行判断

Cat cat = (Cat)animal;

2、接口类型变量指向接口实现类对象

接口的引用类型变量指向接口实现类对象

//没有使用多态
StudentDaoImple studentDao = new StudentDaoImple
//使用多态
StudentDao studnetDao1 = new StudentDaoImpl();

//StudentDao studentDao1 :接口类型的变量
//new StudentDaoImpl():接口实现类对象

好处:

​ 解耦,提高代码的扩展性和可维护性

分层思想(三层架构)

​ 表现层:

​ 用户打交道

​ 业务层

​ 具体实现业务逻辑功能

​ 持久层

​ 数据的持久化

项目中如何体现思想:

​ 分层:创建不同的包

​ 表现层:controller包

​ 业务层:service包

​ 持久层:dao包

3、内部类

匿名内部类

​ 没有名字的类

作用:

​ 给接口创建接口实现类

​ 给抽象类创建子类

​ 创建对象(抽象类/接口)

格式:

new 接口(){
    //实现接口中的抽象方法
};

使用:

​ 如果接口实现类对象,只使用一次,那就可以直接使用匿名内部类进行创建。

​ 一般在传参的时候使用(调用的方法需要一个接口类型的参数,可以直接使用匿名内部类进行传参)

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值