Java编程内存分析简要

本文详细探讨了如何使用Java编程计算五名学生一门课程的平均分,并逐步引入面向对象思想,设计了学生、班级和成绩排序的类结构。后续扩展到多门课程,以及按数学、语文、英语成绩排序,展示了如何利用Comparator进行高效排序。
摘要由CSDN通过智能技术生成

需求1:计算五名学生,一门课程的平均分。

分析数据存储:

Java语言中存储数据的方式有几种?
(1)简单变量,例如int age;
(2)数组,例如,int []age,定义一个数组相当于一次定义了多个变量,这些变量都是相同类型的。
(3)集合,集合存储不同类型的多个变量

数组存储数据(1)

package tests;

public class Test1 {
	public static void main(String[] args) {
		//定义数组存储成绩
		int[] score = null;	
		//存入成绩
		for(int i = 0; i < score.length;i++) { 
			score[i] = 80;
		}
		//打印成绩
		for(int i : score) {
			System.out.print(i+",");
		}
	}
}

运行时出现空指针异常。
在这里插入图片描述

数组存储数据(2)

Test1之所以出现空指针异常是由于没有给数组score申请内存,接下来给数组score申请内存后如下:

package tests;

public class Test2 {
	public static void main(String[] args) {
		int[] score = new int[5];
		
		for(int i = 0; i < score.length;i++) {
			score[i] = 80 + i;
		}
		
		for(int i : score) {
			System.out.println(i+"分");
		}
	}
}

在这里插入图片描述

数组存储数据(3)

Test2中虽然解决了空指针异常的情况,但是,却无法知道成绩具体所指向的学生是谁??所以要先创建一个学生类(Students),具体如下:

package tests;

public class Test3 {
	public static void main(String[] args) {
		// 定义引用类型数组
		Students[] stu = new Students[2];
		// 给数学成绩赋值
		for(int i = 0; i < stu.length;i++) {
			stu[i].math = 80;
		}
		//打印成绩
		for(Students i : stu) {
			System.out.println(i+"分");
		}
	}
}

在这里插入图片描述
解析:出现空指针异常,这是由于只创建了Studnets类,但是没有创建学生对象new Students();
(连学生对象都不存在,如何给学生对象的数学成绩赋值呢,所以报空指针异常。)

解决办法:创建学生后再给数学成绩赋值。
student class

package tests;

public class Students {
	int math; //数学成绩
}

Test Class

package tests;

public class Test4 {
	public static void main(String[] args) {
		Students[] stu = new Students[2];
		//创建学生对象
		for(int i = 0; i < stu.length;i++) {
			stu[i] = new Students();
		}
		
		for(int i = 0; i < stu.length;i++) {
			stu[i].math = 80 + i;
		}
		
		for(Students i : stu) {
			System.out.println(i.math+"分");
		}
	}
}

在这里插入图片描述
解释:
首先要明白
基本类型中存储的是真正的数据,引用数据类型存储的都是地址编号。
Students类是引用数组类型,因此,stu[0]stu[1]存储的是地址,而数学成绩是基本数据类型(int),其存储的是值。

关于需求1使用面向对象程序设计思想的思考。

相对于简单变量与数组解决这个需求1时,数组更好,因为数组的扩展性好,例如更改了学生数量,数组的维护成本小得多.

但是需求1中的数组实现方式中,如果要增加课程,应该怎么设计呢?显然需要增加数组的个数,让一个数组表示一门课程,有几门课程就定义几个数组。这种设计方法没有体现面向对象的思想,因此无法使用面向对象的特征来解决需求变化的问题.

关于需求1使用面向对象程序设计思想的思考
面向对象认为:万物皆对象,也就是任何事物都是对象.
更具面向对象的思想并结合需求1来设计该程序:

	将班级设计为:班级类(名称,学生,平均分)
	将学生设计为:学生类(姓名,数学成绩)
	将程序启动的文件命名为:Tes t.

Student

package tests;

public class Student {
	String name; //姓名
	int maht;//数学成绩
}

ClassInfo

package tests;

public class ClassInfo {
	String name; //班级名称
	Student[] stus = new Student[5];//学生
	public int getMathAverage() {  //数学成绩平均值
		int sum = 0;
		for(int i = 0;i < stus.length;i++) {
			sum += stus[i].maht;
		}
		return sum/stus.length;
	}
}

Test

package tests;

import java.util.Random;

public class Test {
	public static void main(String[] args) {
		// 创建班级
		ClassInfo cla = new ClassInfo();
		cla.name = "史莱克学院n期";
		// 输入班级学生的信息
		for(int i = 0;i < cla.stus.length;i++) {
			cla.stus[i].name = "唐"+(i+1);
			cla.stus[i].maht = new Random().nextInt(40) + 60;
			System.out.println(cla.stus[i].name + " " + cla.stus[i].maht);
		}
		// 计算平均数学成绩
		int mathAverage = cla.getMathAverage();
		System.out.println("数学平均成绩:"+mathAverage);	
	}
}

运行结果:“java.lang.NullPointerException”
分析如下图:
在这里插入图片描述
解析:
在创建班级时,学生类也就一并创建了,但是没有创建学生对象;因此在给具体学生对象输入信息时,先要实现对象的实例化。

// 实例化学生对象并输入班级学生的信息
		for(int i = 0;i < cla.stus.length;i++) {
			cla.stus[i] = new Student(); //实例化学生对象
			cla.stus[i].name = "唐"+(i+1);
			cla.stus[i].maht = new Random().nextInt(40) + 60;
		}

创建学生对象之后,运行后的Java内存分配如下图:
在这里插入图片描述

需求2:计算五名学生,三门课程的平均分。

设计类

面向对象中如何分析问题,设计类,设计类的成员.
分析类:找出问题中描述的名词,每个名词设计为一个类.

例如: 统计班级五个学生数学、语文和英语成绩平均分。

其中的 班级, 学生是名词,应该设计为类,因此设计一个班级类和一个学生类,用类图表示类,如下所示
在这里插入图片描述

设计类的成员

例如:班级中有学生,因此学生是班级的一个属性;平均分是班级的属性;将班级类设计如下

班级类图

学生类有数学、语文和英语成绩和学生姓名,学生类的类图如下

学生类图

代码实现

Student

package tests;

public class Student {
	String name; //姓名
	int math;//数学成绩
	int ch; //语文成绩
	int en; //英语成绩
}

ClassInfo

package tests;

public class ClassInfo {
	String name; //班级名称
	Student[] stus = new Student[5];//学生
	int mathAvg; //数学平均成绩
	int chAvg; //语文平均成绩
	int enAvg; //英语平均成绩
	
	public int getMathAverage() {  //数学成绩平均值
		int sum = 0;
		for(int i = 0;i < stus.length;i++) {
			sum += stus[i].math;
		}
		mathAvg = sum/stus.length;
		return mathAvg;
	}
	public int getChAverage() {  //语文成绩平均值
		int sum = 0;
		for(int i = 0;i < stus.length;i++) {
			sum += stus[i].ch;
		}
		chAvg = sum/stus.length;
		return chAvg;
	}
	public int getEnAverage() {  //英语成绩平均值
		int sum = 0;
		for(int i = 0;i < stus.length;i++) {
			sum += stus[i].en;
		}
		enAvg = sum/stus.length;
		return enAvg;
	}
}

Test

package tests;

import java.util.Random;

public class Test {
	public static void main(String[] args) {
		// 创建班级
		ClassInfo cla = new ClassInfo();
		cla.name = "史莱克学院n期";
		// 实例化学生对象并输入班级学生的信息
		System.out.println("\n\t\t"+cla.name+"成绩单\n\n\t姓名\t数学\t语文\t英语\n");
		for(int i = 0;i < cla.stus.length;i++) {
			cla.stus[i] = new Student();//创建学生对象
			cla.stus[i].name = "唐"+(i+1);
			cla.stus[i].math = new Random().nextInt(40) + 60;
			cla.stus[i].ch = new Random().nextInt(40) + 60;
			cla.stus[i].en = new Random().nextInt(40) + 60;
			System.out.println("\t"+cla.stus[i].name
					+ "\t"+cla.stus[i].math
					+ "\t"+cla.stus[i].ch
					+ "\t"+cla.stus[i].en);
		}
		// 输出平均成绩
		System.out.println("\n\t数学平均成绩:"+cla.getMathAverage());
		System.out.println("\t语文平均成绩:"+cla.getChAverage());
		System.out.println("\t英语平均成绩:"+cla.getEnAverage());
	}
}

增加需求:根据每名同学平均成绩进行排序输出。

第1步:定义排序类

首先按照数学排序,排序类必须是实现了java.util.Comparator接口的类,并且要实现int compare(Student s1, Student s2)比较方法,该方法返回int类型的数据,当返回值大于0时,表示s1大于s2,当返回值等于0时,表示s1等于s2,当返回值小于0时表示s1小于s2.

AverageScoreComparator

package tests;

import java.util.Comparator;

public class AverageScoreComparator implements Comparator<Student>{

	@Override
	public int compare(Student o1, Student o2) {
		return (o1.math + o1.ch + o1.en) - (o2.math + o2.ch + o2.en);
	}

}

ClassInfo类中定义查看成绩的方法shouAvgScore().

public void showAvgScore() {
		System.out.println("\t姓名\t平均 成绩");
		for(int i = 0;i < stus.length;i++) {
			System.out.println("\t"+stus[i].name+"\t平均 成绩"+(stus[i].math + stus[i].ch + stus[i].en)/3);
		}
	}

第2步:使用Arrays类的sort方法排序

Arrays.sort(cla.stus,new AverageScoreComparator());

完整的测试类如下:

package tests;

import java.util.Arrays;
import java.util.Random;


public class Test {
	public static void main(String[] args) {
		// 创建班级
		ClassInfo cla = new ClassInfo();
		cla.name = "史莱克学院n期";
		// 实例化学生对象并输入班级学生的信息
		System.out.println("\n\t\t"+cla.name+"成绩单\n\n\t姓名\t数学\t语文\t英语\n");
		for(int i = 0;i < cla.stus.length;i++) {
			cla.stus[i] = new Student();//创建学生对象
			cla.stus[i].name = "唐"+(i+1);
			cla.stus[i].math = new Random().nextInt(40) + 60;
			cla.stus[i].ch = new Random().nextInt(40) + 60;
			cla.stus[i].en = new Random().nextInt(40) + 60;
			System.out.println("\t"+cla.stus[i].name
					+ "\t"+cla.stus[i].math
					+ "\t"+cla.stus[i].ch
					+ "\t"+cla.stus[i].en);
		}
		// 输出平均成绩
		System.out.println("\n\t数学平均成绩:"+cla.getMathAverage());
		System.out.println("\t语文平均成绩:"+cla.getChAverage());
		System.out.println("\t英语平均成绩:"+cla.getEnAverage());
		
		System.out.println("排序前三门成绩平均分");
		cla.showAvgScore();
		Arrays.sort(cla.stus,new AverageScoreComparator());
		System.out.println("排序后三门成绩平均分");
		cla.showAvgScore();
	}
}

结果展示:
在这里插入图片描述

需求3:计算多名学生,多门课程的平均分

并按数学、语文、英语和总成绩排序。

分析:

被操作的数据是数学、语文和英语,数学、语文和英语属于学生类;需要操作的内容是平均分,平均分属于班级,人数不确定所以不能使用数组,应该使用集合存储数据。

设计:

设计学生类:定义数学、语文和英语属性
设计班级类:定义学生类的集合,定义班级的平均分,定义计算平均分的方法
设计测试类:运行程序

代码实现

Student

public class Student {
    private String name;
    private int math;
    private int ch;
    private int en;

    public Student(String name, int math, int ch, int en) {
        this.name = name;
        this.math = math;
        this.ch = ch;
        this.en = en;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

    public int getMath() {
        return math;
    }

    public int getCh() {
        return ch;
    }

    public int getEn() {
        return en;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public void setCh(int ch) {
        this.ch = ch;
    }

    public void setEn(int en) {
        this.en = en;
    }
}

ClassInfo

import java.util.List;

public class ClassInfo {
    private List students;
    private int avgMath;
    private int avgCh;
    private int avgEn;

    public List getStudents() {
        return students;
    }

    public void setStudents(List students) {
        this.students = students;
    }

    public int getAvgMath() {
        int sum = 0;
        for (int i = 0; i < students.size(); i++) {
            Student stu = (Student) students.get(i);
            sum += stu.getMath();
        }
        avgMath = sum / students.size();
        return avgMath;
    }

    public int getAvgCh() {
        int sum = 0;
        for (int i = 0; i < students.size(); i++) {
            Student stu = (Student) students.get(i);
            sum += stu.getCh();
        }
        avgCh = sum / students.size();
        return avgCh;
    }

    public int getAvgEn() {
        int sum = 0;
        for (int i = 0; i < students.size(); i++) {
            Student stu = (Student) students.get(i);
            sum += stu.getEn();
        }
        avgEn = sum / students.size();
        return avgEn;
    }
}

Test

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
//      创建班级
        ClassInfo c1 = new ClassInfo();
//      创建学生
        Student s1 = new Student("唐1",77,77,77);
        Student s2 = new Student("唐2",78,78,78);
        Student s3 = new Student("唐3",79,79,79);
        Student s4 = new Student("唐4",80,80,80);
        Student s5 = new Student("唐5",81,81,81);
//      将学生存储到集合中
        List students = new ArrayList();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        students.add(s5);
//      将集合存储到班级中
        c1.setStudents(students);
//      输出学生的平均成绩
        System.out.println("平均数学成绩:"+c1.getAvgMath());
        System.out.println("平均数学成绩:"+c1.getAvgCh());
        System.out.println("平均数学成绩:"+c1.getAvgEn());

    }
}

需求4:计算多名学生,多门课程的平均分,并分别按数学、语文、英语成绩排序输出。

只需要在需求3的基础上加以改进就行,不过首先要知道一下两点:

  • 对数组排序,java提供了java.util.Arrays类,调用sort方法实现排序,需要传入比较器
  • 对集合排序,java提供了java.util.Collections类,调用sort方法实现排序,需要传入比较器

针对于数学、语文和英语分别进行比较器的设计如下:
MathComparator

import java.util.Comparator;

public class MathComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getMath() - o2.getMath();
    }
}

ChComparator

import java.util.Comparator;

public class ChComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getCh() - o2.getCh();
    }
}

EnComparator

import java.util.Comparator;

public class EnComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getEn() - o2.getEn();
    }
}

接下来还需要在ClassInfo中添加,查看成绩的方法,如下所示:

public void showByMant(){
        for (int i = students.size() - 1; i >= 0; i--) {
            Student stu = (Student) students.get(i);
            System.out.println(stu.getName() + " " + stu.getMath());
        }
    }
    public void showByCh(){
        for (int i = students.size() - 1; i >= 0; i--) {
            Student stu = (Student) students.get(i);
            System.out.println(stu.getName() + " " + stu.getCh());
        }
    }
    public void showByEn(){
        for (int i = students.size() - 1; i >= 0; i--) {
            Student stu = (Student) students.get(i);
            System.out.println(stu.getName() + " " + stu.getEn());
        }
    }

最后在Test类中添加如下代码就可以测试结果了:

//      数学成绩排序后输出
        Collections.sort(c1.getStudents(),new MathComparator());
        c1.showByMant();
        Collections.sort(c1.getStudents(),new ChComparator());
        c1.showByCh();
        Collections.sort(c1.getStudents(),new EnComparator());
        c1.showByEn();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值