【Java】面向对象笔记(上)

开篇

主线

  1. 类及类的成员

    属性、方法、构造器;

    代码块,内部类

  2. 面向对象三大特征

    继承、封装、多态

  3. 其他关键字

    this,super,static,final,abstract,interface

面向对象的两个要素

一、是什么

类:对一类事物的描述,是抽象的、概念上的定义

对象:是实际存在的该类事物的每个个体,因而也称为实例(instance)

  • 面向对象程序设计的重点是类的设计

  • 设计类,就是设计类的成员。(这个设计是动词)

二、类和对象的使用(面向对象思想落地的实现):

  1. 创建类,设计类的成员
  2. 创建类的对象
  3. 通过对象.属性对象.方法调用对象的结构

三、如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性。(非static的)

意味着:如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值。

对象的内存解析

【Java】面向对象笔记(上)_第1张图片

实践

public class PersonTest {
	public static void main(String[] args) {
		//2. 创建Person类的对象
		Person p1 = new Person();
		//和这个一样Scanner scanner = new Scanner(System.in);
		
		//调用对象的结构:属性、方法
		//调用属性:“对象.属性”
		p1.name = "Tom";
		p1.isMale = true;
		System.out.println(p1.name);
		
		//调用方法:“对象.方法”
		p1.eat();
		p1.sleep();
		p1.talk("Chinese");
		
		//*******************************
		Person p2 = new Person();
		System.out.println(p2.name);//null
		System.out.println(p2.isMale);
		//*******************************
		//将p1变量保存的对象地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
		Person p3 = p1;
		System.out.println(p3.name);//Tom
		
		p3.age = 10;
		System.out.println(p1.age);//10
		
	}
}

//1.创建类,设计类的成员
class Person{
	
	//属性
	String name;
	int age = 1;
	boolean isMale;
	
	//方法
	public void eat(){
		System.out.println("人可以吃饭");
	}
	
	public void sleep(){
		System.out.println("人可以睡觉");
	}
	
	public void talk(String language){
		System.out.println("人可以说话,使用的是:" + language);
	}
	
}

类的成员

属性

属性(成员变量) vs 局部变量

  1. 相同点:

    • 定义变量的格式:数据类型 变量名 = 变量值
    • 先声明,后使用
    • 变量都有其对应的作用域
  2. 不同点:

    1. 在类中声明的位置的不同
      属性:直接定义在类的一对{}
      局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量

    2. 关于权限修饰符的不同
      属性:可以在声明属性时,指明其权限,使用权限修饰符。
      常用的权限修饰符:缺省(不写时默认)、private、public、protected —>详细在封装性中

      目前,大家声明属性时,都使用缺省就可以了。

      局部变量:不可以使用权限修饰符。

    3. 默认初始化值的情况:

      • 属性:类的属性,根据其类型,都有默认初始化值。
        整型(byte、short、int、long):0
        浮点型(float、double):0.0
        字符型(char):0 (或’\u0000’)
        布尔型(boolean):false
        引用数据类型(类、数组、接口):null
      • 局部变量:没有默认初始化值。
        意味着,我们在调用局部变量之前,一定要显式赋值。
        特别地:形参在调用时,我们赋值即可。
  3. 在内存中加载的位置:
    属性:加载到堆空间中 (非static)
    局部变量:加载到栈空间

  4. 总结

成员变量 局部变量
声明的位置 直接声明在类中 方法形参或内部、代码块内、构造器内等
修饰符 private、public、static、final等 不能用权限修饰符修饰,可以用final修饰
初始化值 有默认初始化值 没有默认初始化值,必须显式赋值,方可使用
内存加载位置 堆空间 或 静态域内 栈空间

方法

方法的声明格式:

【Java】面向对象笔记(上)_第2张图片

注意:static、final、abstract 来修饰的方法,后面再讲。

说明:

  1. 关于权限修饰符:默认方法的权限修饰符先都使用public
    Java规定的4种权限修饰符:private、public、缺省、protected -->封装性再细说
  2. 返回值类型: 有返回值 vs 没有返回值
    • 如果方法有返回值,则必须在方法声明时,指定返回值的类型。同时,方法中,需要使用return关键字来返回指定类型的变量或常量:“return 数据”。
    • 如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return.但是,如果使用的话,只能“return;”表示结束此方法的意思。
    • 我们定义方法该不该有返回值?
      ① 题目要求
      ② 凭经验:具体问题具体分析
  3. 方法名:属于标识符,遵循标识符的规则和规范,“见名知意”
  4. 形参列表: 方法可以声明0个,1个,或多个形参。
    • 格式:数据类型1 形参1,数据类型2 形参2,…
    • 我们定义方法时,该不该定义形参?
      ① 题目要求
      ② 凭经验:具体问题具体分析
  5. 方法体:方法功能的体现。

return关键字的使用:

  1. 使用范围:使用在方法体中
  2. 作用:
    ① 结束方法
    ② 针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。
  3. 注意点:return关键字后面不可以声明执行语句。

递归调用

  • 方法的使用中,可以调用当前类的属性或方法

    特殊的:方法A中又调用了方法A:递归方法。

  • 方法中,不可以定义方法。⭐

练习

  1. 利用面向对象的编程方法,设计类Circle计算圆的面积。
package com.atguigu.exer;

public class CircleTest {
	public static void main(String[] args) {
		Circle circle = new Circle();
		circle.radius = 2;//半径
		System.out.println(circle.findArea());
	}
}

//圆
class Circle{
	double radius;

	public double findArea() {
		return Math.PI * radius * radius;
	}
}
  1. 编写程序,声明一个printMatrix方法,在方法中打印一个4行3列的*型矩形,在main方法中调用该方法。
public class Exer3Test {
	public static void main(String[] args) {
		Exer3Test test = new Exer3Test();
		test.printMatrix();
	}
	public void printMatrix() {
		for (int i = 0; i < 4;i++){
			for(int j = 0; j < 3;j++){
				System.out.print("* ");
			}
			System.out.println();
		}
	}
}
  1. 修改上一个程序,在printMatrix方法中,除打印一个4行3列的*型矩形外,再计算该矩形的面积,并将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
public class Exer3Test {
	public static void main(String[] args) {
		Exer3Test test = new Exer3Test();
		System.out.println("面积是:" + test.printMatrix());
	}
	
	public int printMatrix() {
		for (int i = 0; i < 4;i++){
			for(int j = 0; j < 3;j++){
				System.out.print("* ");
			}
			System.out.println();
		}
		return 4 * 3;//返回矩形面积
	}
}
  1. 修改上一个程序,在printMatrix方法提供rowcolumn两个参数,方法中打印一个m*n*型矩形,并计算该矩形的面积, 将其作为方法返回值。在main方法中调用该方法,接收返回的面积值并打印。
public class Exer3Test {
	public static void main(String[] args) {
		Exer3Test test = new Exer3Test();
		System.out.println("面积是:" + test.printMatrix(4,3));
	}
	
	public int printMatrix(int row, int column) {
		for (int i = 0; i < row;i++){
			for(int j = 0; j < column;j++){
				System.out.print("* ");
			}
			System.out.println();
		}
		return row * column;//返回矩形面积
	}
}
  1. 对象数组题目:

定义类Student,包含三个属性:学号number(int),年级state(int),成绩score(int)。创建20个学生对象,学号为1到20,年级和成绩都由随机数确定。

  • 问题一:打印出3年级(state值为3)的学生信息。

  • 问题二:使用冒泡排序按学生成绩排序,并遍历所有学生信息

提示:

  1. 生成随机数:Math.random(),返回值类型double;

  2. 四舍五入取整:Math.round(double d),返回值类型long。

public class Exer3Test {
	public static void main(String[] args) {
		//对象数组,当作引用数据类型即可
		Student[] stus = new Student[20];
		for(int i = 0; i < stus.length; i++){
			stus[i] = new Student();//赋值(对象)
			stus[i].number = (i+1);
			stus[i].state = (int)(Math.random() * (6 - 1 + 1) + 1);
			stus[i].score = (int)(Math.random() * (100 + 1));
		}
		//输出成绩:打印出3年级(state值为3)的学生信息
		for (int i = 0; i < stus.length; i++) {
			if (stus[i].state == 3) {
				System.out.println(stus[i].showInfo());
			}
		}
		System.out.println("---------------------------");
		//使用冒泡排序按学生成绩排序,并遍历所有学生信息
		for (int i = 0; i < stus.length - 1; i++) {
			for (int j = 0; j < stus.length - 1 - i; j++) {
				if (stus[j].score > stus[j+1].score) {
					Student temp = stus[j];
					stus[j] = stus[j+1];
					stus[j+1] = temp;
				}
			}
		}
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].showInfo());
		}
	}
}
/**
 * Student
 */
class Student {
	int number;
	int state;
	int score;

	public String showInfo() {
		return "学号:" + number + ",年级:" + state + ",成绩:" + score;
	}
}

改进,将其中的方法进行封装。优雅!!!

public class Exer3Test {
	public static void main(String[] args) {

		//对象数组,当作引用数据类型即可
		Student[] stus = new Student[20];
		for(int i = 0; i < stus.length; i++){
			stus[i] = new Student();//赋值(对象)
			stus[i].number = (i+1);
			stus[i].state = (int)(Math.random() * (6 - 1 + 1) + 1);
			stus[i].score = (int)(Math.random() * (100 + 1));	
		}

		//输出成绩:打印出3年级(state值为3)的学生信息
		Exer3Test test = new Exer3Test();
		test.searchState(stus, 3);
		System.out.println("---------------------------");
		//使用冒泡排序按学生成绩排序,并遍历所有学生信息
		test.bobuleSort(stus);
		test.print(stus);

	}

	/**
	 * 查找指定年级的学生并输出
	 * @param stus 要查找的学生数组
	 * @param state 要查找的年级
	 */
	public void searchState(Student[] stus, int state){
		for (int i = 0; i < stus.length; i++) {
			if (stus[i].state == state) {
				System.out.println(stus[i].showInfo());
			}
		}
	}
	
	/**
	 * 冒泡排序数组
	 * @param stus 要排序的数组
	 */
	public void bobuleSort(Student[] stus){
		for (int i = 0; i < stus.length - 1; i++) {
			for (int j = 0; j < stus.length - 1 - i; j++) {
				if (stus[j].score > stus[j+1].score) {
					Student temp = stus[j];
					stus[j] = stus[j+1];
					stus[j+1] = temp;
				}
			}
		}
	}

	/**
	 * 遍历输出数组
	 * @param stus	要遍历的数组
	 */
	public void print(Student[] stus){
		for (int i = 0; i < stus.length; i++) {
			System.out.println(stus[i].showInfo());
		}
	}
	
}
/**
 * Student
 */
class Student {
	int number;
	int state;
	int score;
	public String showInfo() {
		return "学号:" + number + ",年级:" + state + ",成绩:" + score;
	}
}
  1. 声明一个日期类型Date:有属性:年year,月month,日day。 创建2个日期对象,分别赋值为:你的出生日期,你对象的出生日期, 并显示信息。

    “没有对象,我很抱歉。” --鲁迅

public class Exer3Test {
	public static void main(String[] args) {
		Date myDate = new Date();
		Date exDate = new Date();
		myDate.setDate(2000, 10, 26);
		exDate.setDate(2000, 3, 11);
		System.out.println("我的生日" + myDate.print());
		System.out.println("前任生日" + exDate.print());
	}
}

class Date {
	int year;
	int month;
	int day;

	public void setDate(int year,int month,int day){
		this.year = year;
		this.month = month;
		this.day = day;
	}

	public String print() {
		return ("生日为:" + year + "年"
		 + month + "月" + day + "日。");
	}
}

理解“万事万物皆对象”

  1. 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构
  • Scanner,String等
  • 文件:File
  • 网络资源:URL
  1. 涉及到Java语言与前端Html、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象。

匿名对象

我们创建的对象,没有显式的赋给一个变量名。即为匿名对象

使用场景

  1. 类中的方法仅被对象调用一次

    Person p = new Person();	//正常的对象
    new Person();	//匿名对象
    new Person().talk();//只调用一次
    
  2. 匿名对象做实参传递

    Person.show(new Person());      //匿名对象做实际参数。
    
  3. 错误的使用方法

    new Person().eat(new Food().name = "大饼"); 
    //不可以在创建的同时赋值,所以要么做实参,要么调方法。
    

区别及内存分析

除了做实参,你只能调用一次。例如下面的代码

//正常对象
Person p = new Person();
p.name = "yuan";
p.age = 19;

//匿名对象
new Person().name = "yuan";
new Person().age = 19;

这是正常对象在内存的映射

这是匿名对象在内存的映射,它不会在占空间中占据内存,并且每new一次,就是一个新的匿名对象。

这部分的参考:

你可能感兴趣的:(JAVA,java,开发语言)