面向对象

面向对象

一、IDEA的一些基本使用

网址:IntelliJ IDEA – 领先的 Java 和 Kotlin IDE (jetbrains.com)

创建IDEA工程:

  • 创建一个空的工程

image

image

设置主题和字体设置

image

image

image-20230311164311721

Alt+Shift+Up/Down 上/下移一行
Ctrl+D 复制行
Ctrl+X 删除行
Ctrl+Y 删除当前行
Ctrl+Shift+U 大小写转化
Shift+Enter 向下插入新行
Ctrl+Shift+Space 自动补全代码
Alt+Insert 以生成构造器/Getter/Setter等

二、面对对象

什么的面向对象:

用程序去模拟现实世界,因为这是最直观的。

1.什么是对象

万物皆对象,是真正存在的事物

是对类的一个具象,是一个实体。

2.什么是类

  • 具有共性的一组事物的抽象(模板),叫做类,是一个概念而不是具体的事物

  • 通常是对一组具有相同特性的对象,将其共性抽取出来

  • 在程序当中:类是一个文件

3.对象的构成

  • 特性(属性):可以落于纸面,可以进行量化,可以描述

  • 行为(方法):用于表示过程,行为

    没有任何一个事物可以脱离场景独立存在,类的扩展可以在水平(同一类型,不同的展示)扩展,也可以在垂直(上级类型/下级类型)扩展

4.类的创建

  1. IDEA当中创建模块

image

语法:

使用关键字:class

public class Person{
    
}

类的成员

public class Person {
	//属性
	public int id;
	public String name;
	public int sex;
	public int age;
	//方法
	public void say(){
		System.out.println("我真帅");
	}
	public void sleep(){
		System.out.println("在哪里跌倒,就在哪里睡着");
	}
}
  • 属性(成员变量)的结构:
    • 访问修饰符 属性类型 属性名
  • 方法(成员方法)的结构
    • 访问修饰符 返回值类型(void) 方法名(方法体)

注意:

方法发书写非常的灵活,这里仅仅是演示方法的使用

5.创建对象

语法:

类名 对象名 = new 类名/构造方法名();

案例

public class Main {
	public static void main(String[] args) {
	//对象的创建
	Person a = new Person();
	a.id = 1;
	a.name = "df";
	a.sex = 1;
	a.age = 18;
	Person b = new Person();
	b.id = 2;
	b.name = "shmily";
	b.sex = 0;
	b.age = 16;
	System.out.println("df的姓名"+a.name);
	System.out.println("shmily的姓名"+b.name);
	}
}
  • 给对象的属性赋值

语法:

对象名.属性名 = 值;
  • 从对象的属性取值

语法:

变量类型 变量名 = 对象名.属性名;
  • 方法的调用
public class Main2 {
	public static void main(String[] args) {
	//对象的创建
	Person a = new Person();
	a.say();
	Person b = new Person();
	b.say();
	}
}

语法:

对象名.方法名();

注意:
任何对象,如果没有实例化,则直接调用时,会出现空指针异常。

Exception in thread "main" java.lang.NullPointerException

什么是实例化:

new出来的这个部分就是实例,new的这个行为叫做实例化

匿名实例化:

public class Main2 {
	public static void main(String[] args) {
	//对象的创建
	Person df = new Person();
	//匿名创建对象
	new Person();
	new Person().name = "DF";//匿名属性赋值
	new Person().say();//匿名方法调用
	}
}

注意:
1.属于一次性消耗
2.只要看见new关键字,就是一个新的对象

课间作业

  • 在教室中找素材创建10个类
  • 为每一个类,赋予足够多的属性和方法(10属性,5个方法)
  • 为每个类创建其对象,并赋予属性值,同时调用所有的方法

Fan.java

package com.mine.student;

public class Fan {
    //风扇
    public int fanId;
    public String fanName;
    public String color;
    public String fanLong;
    public String fanWide;
    public String fanHigh;
    public double fanPrice;
    public String fanMaterial;
    public String factoryTime;
    public double serviceLife;

    public void open() {
        System.out.println("风扇开始旋转~~~");
    }

    public void close() {
        System.out.println("风扇开始停止~~~");
    }

    public void speedUp() {
        System.out.println("调快风扇转速~~~");
    }

    public void speedDown() {
        System.out.println("调慢风扇转速~~~");
    }

    public void rollback() {
        System.out.println("风扇开始逆时针旋转~~~");
    }
}

Cup.java

package com.mine.student;

public class Cup {
    //杯子
    public int cupId;
    public String cupName;
    public String color;
    public double cupLong;
    public double cupWide;
    public double cupHigh;
    public String cupMaterial;
    public String cupCapacity;
    public String cupSpecification;
    public double cupPrice;
    public void fillWater(){
        System.out.println("装水~~~");
    }
    public void tea(){
        System.out.println("泡茶~~~");
    }
    public void bubbleGoji(){
        System.out.println("泡枸杞~~~");
    }
    public void driedMilk(){
        System.out.println("泡奶粉~~~");
    }
    public void coffee(){
        System.out.println("泡咖啡~~~");
    }
}

Main.java

package com.mine.student;

public class Main {
    public static void main(String[] args) {
        //风扇
        Fan fan = new Fan();
        fan.fanId = 1;
        fan.fanName = "风扇";
        fan.color = "pink";
        fan.fanPrice = 66.6;
        fan.fanLong = "50cm";
        fan.fanWide = "30cm";
        fan.fanHigh = "1cm";
        fan.factoryTime = "2022-10-18";
        fan.fanMaterial ="金属";
        System.out.println("编号:"+fan.fanId+",名字:"+fan.fanName+",颜色:"+fan.color+",价格:"+fan.fanPrice);

        String str = String.format("%s的编号是:%d,颜色%s,价格%f,长:%s,宽:%s,高:%s,出厂时间:%s,材质:%s",fan.fanName,
                fan.fanId,fan.color,fan.fanPrice,fan.fanLong,fan.fanWide,fan.fanHigh,fan.factoryTime,fan.fanMaterial);
        System.out.println(str);

        //茶杯
        Cup cup = new Cup();
        cup.cupId = 2;
        cup.cupName = "SUPER";
        cup.color = "Black";
        cup.cupMaterial = "304不锈钢";
        cup.cupPrice = 99.99;
        System.out.println("编号:"+cup.cupId+",名字:"+cup.cupName+",颜色:"+cup.color+",价格:"+cup.cupPrice+",材质:"+cup.cupMaterial);



    }
}


结果:
编号:1,名字:风扇,颜色:pink,价格:66.6
风扇的编号是:1,颜色pink,价格66.600000,长:50cm,宽:30cm,高:1cm,出厂时间:2022-10-18,材质:金属
编号:2,名字:SUPER,颜色:Black,价格:99.99,材质:304不锈钢

三、方法

什么是方法:

可以实现特定功能的代码,可以重复使用。

我们不需要知道方法的内部是如何执行的,我们只需要知道,我应该给这个方法提供什么样的参数,以及该方法可以返回给我的返回值

1.定义语法

访问修饰符 返回值类型 方法名 (形参列表){
	方法体
	return 返回值
}

2.返回值

两个大类:

  1. void:没有返回值
public class Person {
	public void say(){
		System.out.println("巴拉巴拉");
	}
}
public class Main {
	public static void main(String[] args) {
		Person p = new Person();
		p.say();//调用就行,不需要返回任何东西
	}
}
  1. 有返回值(返回值类型

注意:

返回值的类型可以任意,但是注意,这里是类型,不是值。
使用关键字return返回具体的值

public class Person {
	public String say(){
		return "巴拉巴拉";//返回的值,必须和声明的返回值类型保持一致
	}
}
public class Main {
	public static void main(String[] args) {
		Person p = new Person();
		String result = p.say();//调用者调用方法得到的结果,可以使用相同类型的变量承接
	}
}

返回值的类型和返回的值,以及调用者用于承接结果的变量类型都需要保持一致

3.return关键字

return在有返回值的情况下,必须存在,且只能执行一次

在没有返回值的情况下,可有可没有

案例:

  1. 在void返回值类型的情况下
public class Person {
	public void say(){
		int i = 1;
		if(i > 0){
			System.out.println("在这里返回,终止程序继续运行");
			return;//如果执行了,方法立即终止
		}
		System.out.println("这是后续内容");
	}
}
public class Main {
	public static void main(String[] args) {
		Person person = new Person();
		person.say();
	}
}

结果:
在这里返回,终止程序继续运行
  1. 如果有返回值
public class Person {
public void say(){
	int i = 1;
    	if(i > 0){
			System.out.println("在这里返回,终止程序继续运行");
			return;//如果执行了,方法立即终止
			}
		System.out.println("这是后续内容");
	}
	public int run1(){
		int i = 1;
		if(i > 0){
			System.out.println("作为一个分支1");
			return 100;//无法被计算机确定,肯定能被执行
		}else{
			System.out.println("作为一个分支2");
			return 200;//如果加上else则至少有一个return会被执行
		}
		// System.out.println("这是后续内容");//这里根本无法被执行到
	}
	public int run2(){
		int i = 1;
		if(i > 0){
			System.out.println("作为一个分支1");
			return 100;//无法被计算机确定,肯定能被执行
		}
		System.out.println("这是后续内容");
		return 200;//这个return在排除其他任何一个情况后,确保最终一定会有一个return被执行
	}
}

只要返回值类型不是void,那么必须要提供返回值,即执行return语句,且只能执行一次。

4.方法的参数

作用:往方法内部传递数据

  • 形参
    • 申明语法:
      • 1.可以有0-n个,不同的参数之间,使用逗号分隔
      • 2.必须是某个数据类型,数据类型包含基本数据类型和引用数据类型,不可以是具体的值

案例:

package com.mine.demo1;

public class Cat {
    public void eat(int n,String food){
      	/*
		参数名可以根据需要任意取,参数名和调用方没有关系
		*/
    }
}

方法的参数在方法体当中,可以当做一个普通的,已经被赋值了的变量的使用

package com.mine.demo1;

public class Cat {
    public void eat(int n,String food){
        /*
		参数名可以根据需要任意取,参数名和调用方没有关系
		参数直接当成普通变量使用
		*/
        System.out.println(String.format("咪咪今天吃了%dkg的%s",n,food));
    }
}

  • 实参

    • 1.调用方法时,向方法传递的具体的数据的值
    • 2.形参和实参在调用时的数量、顺序、类型必须保持一致

    案例:

    package com.mine.demo1;
    
    public class Main {
        public static void main(String[] args) {
            Cat cat  = new Cat();
            cat.eat(10,"小鱼干");
        }
    }
    
    结果:
    咪咪今天吃了10kg的小鱼干
    
    • 一个特殊的参数类型,不定长参数,即改方法的实参数量不固定

      • 形参语法

        package com.mine.demo1;
        
        public class Cat {
        //    public void eat(int n,String food){
        //        System.out.println(String.format("咪咪今天吃了%dkg的%s",n,food));
        //    }
        
            //相同的作用,在申明时比数组更加简练
            public void eat(String ... foods){
                //当做普通数组使用
                for(int i =0;i < foods.length;i++){
                    System.out.println(foods[i]);
                }
            }
        }
        
        
      • 实参语法

        package com.mine.demo1;
        
        public class Main {
            public static void main(String[] args) {
                Cat cat  = new Cat();
                //cat.eat(10,"小鱼干");
        
                cat.eat("小鱼干,小虾米,猫粮");//可以传递0-n个该类型的实参
            }
        }
        
        
      • 注意:

        不定长参数,只能在形参列表的末尾,且只能有一个

5.地址传参

地址赋值

案例:

package com.mine.demo2;

public class Cat {
    public String name;
}

package com.mine.demo2;

public class Main {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
        Cat cat2 = new Cat();
        System.out.println(cat1);
        System.out.println(cat2);
    }
}

结果:
com.mine.demo2.Cat@4554617c
com.mine.demo2.Cat@74a14482

结论:

引用数据类型在进行相互赋值时,传递的是内存地址

image

通过方法传参,传递地址

案例:

package com.mine.demo2;

public class Cat {
    public String name;
}

package com.mine.demo2;

public class Master {
    public void feed(Cat cat){
        System.out.println(String.format("方法内的内存地址:%s",cat));
        cat.name = "小猫2";
        System.out.println(String.format("cat的name2:%s",cat.name));
    }
}

package com.mine.demo2;

public class Main {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
//        Cat cat2 = new Cat();
//        System.out.println(cat1);
//        System.out.println(cat2);
        Master master = new Master();
        cat1.name = "小猫1";
        System.out.println(String.format("传递前的内存地址:%s",cat1));
        System.out.println(String.format("cat name1:%s",cat1.name));
        master.feed(cat1);
        System.out.println(String.format("传递后的内存地址:%s",cat1));
        System.out.println(String.format("cat name2:%s",cat1.name));
    }
}

结果:
传递前的内存地址:com.mine.demo2.Cat@5cad8086
cat name1:小猫1
方法内的内存地址:com.mine.demo2.Cat@5cad8086
cat的name2:小猫2
传递后的内存地址:com.mine.demo2.Cat@5cad8086
cat name2:小猫2

image

在方法内部更换对象地址,不影响原本改对象的引用关系

  1. 引用对象内存地址的传递,是需要一个赋值这么个过程的(赋值我才能把地址给你)
  2. 引用当中的数据修改

案例:

package com.mine.demo2;

public class Cat {
    public String name;
}

package com.mine.demo2;

public class Master {
    /*
    每一个方法都有一个独立的方法栈,在该方法栈当中申请的新的内存地址,对其外部调用没有任何影响
     */
    public Cat feed(Cat cat2){
        cat2 = new Cat();
        System.out.println(String.format("2.方法内的内存地址:%s",cat2));
        return cat2;
    }
}

package com.mine.demo2;

public class Main {
    public static void main(String[] args) {
        Cat cat1 = new Cat();      
        Master master = new Master();
        cat1.name = "小猫1";
        System.out.println(String.format("1.传递前的cat2地址:%s",cat1));
        Cat cat2 = master.feed(cat1);
        System.out.println(String.format("3.传递后cat2的内存地址:%s",cat1));
        System.out.println(String.format("4.传递后新建的cat2的内存地址:%s",cat2));

    }
}

结果:
1.传递前的cat2地址:com.mine.demo2.Cat@5cad8086  【传参前】
2.方法内的内存地址:com.mine.demo2.Cat@6e0be858  【方法内部更换的内存引用】
3.传递后cat2的内存地址:com.mine.demo2.Cat@5cad8086  【对原本的引用没有任何影响】
4.传递后新建的cat2的内存地址:com.mine.demo2.Cat@6e0be858  【要获取方法内的新的引用,可以通过返回值来获取】

6.作用域

全局变量:

  1. 全局变量直接申明在类当中
  2. 全局变量有默认值:整数(0),浮点数(0.0),字符(空格),布尔类型(false),引用类型(null)
  3. 在整个类当中,所有区域,所有方法都可以使用,整个类共享
  4. 可以有访问修饰符
  5. 全局变量的基本数据类型在堆当中
public class Person{
    //全局变量:申明在类中
    public int id;
    public String name;
    public Dog dog;
    
}

局部变量:

  1. 在方法当中被使用
  2. 包含:
    • 在方法当中申明的变量
    • 在参数列表当中申明的形参
  3. 局部变量必须赋初值才可以使用
  4. 局部变量不可以使用访问修饰符
  5. 基本数据类型在栈当中

注意:当局部变量和全局变量重名时,优先使用局部变量

了解:使用this关键字

public class Person{
    public int i = 1;
    public void feed(){
        int i = 2;
        System.out.println(this.i); //使用的是全局变量i = 1
    }
}

方法的调用区域

内部调用:在类的内部,调用自身的方法

语法:直接调用,即方法名(实参);

public class Test {
	public void fun1(){
		System.out.println("fun1");
		fun2();//类的内部调用,直接调用
		fun3();
	}
	public void fun2(){
		System.out.println("fun2");
	}
	public void fun3(){
		System.out.println("fun3");
	}
}

外部调用:在类的外部,需要通过创建对象的方式进行调用

public class Main {
	public static void main(String[] args) {
		Test test = new Test();
		test.fun1();
		test.fun2();
		test.fun3();
	}
}

调用区域:

package com.mine.demo08;
//fun();//不允许
public class Test {
// fun();//不允许
	public int i = fun();//允许
	public int fun(){
		return 100;
	}
}
//fun();//不允许

课堂练习

以面向对象的思路完成学生考试成绩录入系统

Student.java

package com.mine.student;

public class Student {
    /**
     * 学生学号
     */
    public int stuId;
    /**
     * 学生名字
     */
    public String stuName;
    /**
     * 学生成绩
     */
    public String stuScore;

}

SystemUtil.java

package com.mine.student;

public class SystemUtil {
    /**
     * 学生成绩排序
     */
    public void sortScore(){

    }
}

ExamSystem.java

package com.mine.student;

import java.util.Scanner;

public class ExamSystem {

    /**
     * 声明scanner对象
     */
    public Scanner scanner;

    /**
     * 初始化
     */
    public void init(){
        scanner = new Scanner(System.in);
        System.out.println("初始化完成!");
    }
    /**
     * 选择功能
     */
    public int selectOption(){
        System.out.println("请选择1.录入学生成绩\t2.展示学生成绩\t3.退出系统");
        return scanner.nextInt();
    }

    /**
     * 录入学生成绩
     */
    public void insertScore(){
        System.out.println("学生成绩录入成功!");
    }

    /**
     * 展示学生成绩
     */
    public void showScore(){
        System.out.println("学生成绩展示成功!");
    }

    /**
     * 退出系统
     */
    public void exit(){
        System.out.println("系统退出成功!");
    }
}

Main.java

package com.mine.student;

public class Main {
    public static void main(String[] args) {
        ExamSystem system = new ExamSystem();
        System.out.println("欢迎使用学生管理系统!");
        system.init();
        boolean flag = true;
        while(flag){
            int num =system.selectOption();
            switch (num){
                case 1:
                    system.insertScore();
                    break;
                case 2:
                    system.showScore();
                    break;
                case 3:
                    system.exit();
                    flag = false;
                    break;
                default:
                    System.out.println("输入错误!");
            }
        }
    }
}

posted @ 2023-03-11 17:53  DFshmily  阅读(10)  评论(0编辑  收藏  举报