1. 向下转型和instanceof关键字

  2. 向下转型的几个常见问题

  3. 多态练习

  4. 剖析Object类

  5. ==运算符与equals()方法

  6. 总结equals()与==

  7. toString()的使用

  8. Object类综合练习

  9. 单元测试方法的使用

  10. 包装类

 

1,向下转型和instanceof关键字

    开发中向上转型(多态)用的最多

package com.atguigu.java;

public class PersonTest {
	public static void main(String[] args) {
		// 向上转型,即多态。类比到基本数据类型,这两步就是自动类型提升和强制类型转换
		Person p = new Man();
		p.eat();
//		p.say(); // 不能调用子类中特有的属性和方法,因为编译器认为Person类型没有这些结构
//		System.out.println(p.isSmoking); // 但这些子类特有的结构实际是加载到了内存的
		// 使用强制类型转换符,向下转型
		Man m = (Man)p; // 引用变量存储的是一个地址值,且这个地址值是由对象类型@内存
						// 地址值组成的,当使用强转后,地址值的对象类型就由Person的变为
						// 了Man的,内存地址值没变。此时编译器知道m是一个Man对象的引用,
						// 所以就能调用Man类型中特有的结构。这个过程就是原来实际存在的被
						// 隐藏的结构现在显现出来了
		m.say();
		m.isSmoking = true;
		// 和基本数据类型的强转可能会损失精度一样,向下转型可能出错
		// Woman w = (Woman)p; // 用一个Woman类型的引用变量引用Man类型对象,运行时报错,类型转换错误
		// w.goShopping(); // A类型的对象只能赋值给本类或其父类的引用
		// 为避免上面的问题,就要使用到instanceof关键字
		// a instanceof A:判断对象a是否是A类型的一个实例,是返回true,否返回false
		// 为避免强转时出现异常,通常在强转时先进行判断
		if(p instanceof Woman) { // false
			Woman w = (Woman)p;
			w.goShopping();
			System.out.println("是一个女人");
		}
		// 一个对象是一个子类的实例,那它一定是这个子类的父类的实例
		// 反之一个对象是一个父类的实例,那它一定是这个父类的子类的实例则不一定对
		if(p instanceof Man) { // true
			
		}
		if(p instanceof Person) { // true
			
		}
		if(p instanceof Object) { // true
			
		}
	}
}

class Person {
	String name;
	
	public void eat() {
		System.out.println("人吃饭");
	}
}

class Man extends Person {
	boolean isSmoking;
	
	public void eat() {
		System.out.println("男人多吃饭");
	}
	
	public void say() {
		System.out.println("我是男人");
	}
}

class Woman extends Person {
	public void goShopping() {
		System.out.println("女人喜欢购物");
	}
}

 

2,向下转型的几个常见问题

package com.atguigu.java1;

public class PersonTest1 {
	public static void main(String[] args) {
		// 1,编译通过,运行不通过
//		Person p1 = new Woman();
//		Man m1 = (Man)p1; // 虽然规定不能将一个父类对象赋值给一个子类引用,但这里只是强转类型是可以通过编译的
//		Person p2 = new Person();
//		Man m2 = (Man)p2;

		// 2,编译通过,运行也通过,开发中可以这样写
		Object obj = new Woman(); // 向上转型/动态
		Person p3 = (Person)obj; // 向下转型
		
		// 3,编译不通过
		// Man m3 = new Woman();
		// String str = new Date();
	}
}

class Person {
	String name;
	
	public void eat() {
		System.out.println("人吃饭");
	}
}

class Man extends Person {
	boolean isSmoking;
	
	public void eat() {
		System.out.println("男人多吃饭");
	}
}

class Woman extends Person {
	public void goShopping() {
		System.out.println("女人喜欢购物");
	}
}

 

3,多态练习

    练习1:

package com.atguigu.java;

public class FieldMethodTest {
	// 堆空间中只有一个对象,但通过不同类型的引用调用它的属性时发现结果不一样
	public static void main(String[] args) {
		Sub s = new Sub();
		System.out.println(s.count); // 20
		s.display(); // 20
		Base b = s; // 多态
		System.out.println(b); // com.atguigu.java.Sub@15db9742
		System.out.println(s); // com.atguigu.java.Sub@15db9742,二者竟然是同类型,前面提到的子父类引用存储的地址是不同类型的可能错了
		System.out.println(b == s); // true;对于引用数据类型,==判断它们存储的对象地址值是否相等
		System.out.println(b.count); // 10;属性没有多态性,编译和运行都看左边
		b.display(); // 20;虚拟方法调用
	}
}

// 开发中尽量不要定义同名的属性
class Base {
	int count = 10;
	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;
	public void display() {
		System.out.println(this.count);
	}
}
    练习2:

package com.atguigu.java1;

public class InstanceTest {
	
	public static void main(String[] args) {
		InstanceTest test = new InstanceTest();
		test.method(new Student());
	}
	
	public void method(Person e){
		String info = e.getInfo(); // 虚拟方法调用
		System.out.println(info);
		
		// 方式一
//		if(e instanceof Graduate) {
//			System.out.println("a graduated student");
//			System.out.println("a student");
//			System.out.println("a person");
//		}else if(e instanceof Student) {
//			System.out.println("a student");
//			System.out.println("a person");
//		}else {
//			System.out.println("a person");
//		}
		
		//方式二
		if(e instanceof Graduate) {
			System.out.println("a graduated student");
		}
		if(e instanceof Student) {
			System.out.println("a student");
		}
		if(e instanceof Person) {
			System.out.println("a person");
		}
	}
}

class Person {
	protected String name = "person";
	protected int age = 50;

	public String getInfo() {
		return "Name: " + name + "\n" + "age: " + age;
	}
}

class Student extends Person {
	protected String school = "pku";

	public String getInfo() {
		return "Name: " + name + "\nage: " + age + "\nschool: " + school;
	}
}

class Graduate extends Student {
	public String major = "IT";

	public String getInfo() {
		return "Name: " + name + "\nage: " + age + "\nschool: " + school + "\nmajor:" + major;
	}
}
    练习3:
    父类

package com.atguigu.java;

public class GeometricObject {
	protected String color;
	protected double weight;
	
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}
	
	public GeometricObject(String color, double weight) {
		super();
		this.color = color;
		this.weight = weight;
	}
	
	public double findArea() { // 不知道子类具体求面积的方法
		return 0.0;
	}
}
    子类Circle

package com.atguigu.java;

public class Circle extends GeometricObject {
	private double radius;
	
	public Circle(String color, double weight, double radius) {
		super(color, weight);
		this.radius = radius;
	}

	public double getRadius() {
		return radius;
	}
	public void setRadius(double radius) {
		this.radius = radius;
	}
	
	public double findArea() {
		return 3.14 * radius * radius;
	}
}
    子类MyRectangle

package com.atguigu.java;

public class MyRectangle extends GeometricObject {
	private double width;
	private double height;
	
	public MyRectangle(String color, double weight, double width, double height) {
		super(color, weight);
		this.width = width;
		this.height = height;
	}
	
	public double getWidth() {
		return width;
	}
	public void setWidth(double width) {
		this.width = width;
	}
	public double getHeight() {
		return height;
	}
	public void setHeight(double height) {
		this.height = height;
	}
	
	public double findArea() {
		return width * height;
	}
}
    测试

package com.atguigu.java;

public class GeometricTest {
	
	public void displayGeometricObject(GeometricObject o) {
		System.out.println("面积为:" + o.findArea());
	}
	
	public boolean equalsArea(GeometricObject o1, GeometricObject o2) { // 传入子类对象,多态
		return o1.findArea() == o2.findArea(); // 虚拟方法调用
	}
	
	public static void main(String[] args) {
		GeometricTest test = new GeometricTest();
		
		Circle c1 = new Circle("white", 1.0, 2.3);
		test.displayGeometricObject(c1);
		Circle c2 = new Circle("white", 1.0, 3.3);
		test.displayGeometricObject(c2);
		
		boolean isEquals = test.equalsArea(c1, c2);
		System.out.println("c1 和 c2的面积是否相等:" + isEquals);
		
		MyRectangle rect = new MyRectangle("red", 2.0, 2.0, 1.0);
		test.displayGeometricObject(rect);
	}
}
    练习4:

package com.atguigu.java1;

//考查多态的笔试题目:
public class InterviewTest {

	public static void main(String[] args) {
		Base base = new Sub();
		base.add(1, 2, 3); // sub_1,虚拟方法调用。不会调用Sub的第二个add方法,因为虚拟方法调用只调用子类重写父类的该方法

		Sub s = (Sub)base;
		s.add(1, 2, 3); // sub_2,优先调用Sub的第二个固定参数的add方法
	}
}

class Base {
	public void add(int a, int ... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) { // int[] arr和int ... arr两种写法,二者其实是一样的,所以这里就是重写方法
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) { // 重载
		System.out.println("sub_2");
	}

}

 

4,剖析Object类

package com.atguigu.java1;

/*
 * java.lang.Object类是所有Java类的根父类
 * 如果类的声明未使用extends明确指明继承哪个父类,则默认继承Object类
 * Object类具有通用性,它没有定义属性,只提供一个空参构造器
 *     Object类有clone()方法,用来复制创建一个完全相同的对象;equals()比较两个对象是否
 *     相等;finalize()当对象被垃圾回收器回收之前会调用的方法;getClass()返回创建当前
 *     对象的类;hashCode()返回对象的哈希值;notify()、notifyAll()、三个wait()与线
 *     程通信有关;toString()转换为字符串
 */

public class ObjectTest {
	
	public static void main(String[] args) {
		Order order = new Order();
		System.out.println(order.getClass().getSuperclass()); // java.lang.Object
	}
}

class Order {
	
}

 

5,==运算符和equals()方法

package com.atguigu.java1;

import java.util.Date;

/*
 * ==运算符:
 *     可以用来比较基本数据类型和引用数据类型
 *     比较基本数据类型时,比较的是两个变量保存的数据是否相等,不一定要类型相同
 *     比较引用数据类型时,比较的是两个引用存储的地址值是否相同,即两个引用是否指向同一对象
 * equals()方法:
 *     用来比较两个对象是否相等。是一个方法而非运算符,所以只适用于引用数据类型
 *     比较两个不同对象是否相等,首先它们要是同类型的(包括子父类关系,一个子类对象也是其父类
 *     的一个实例),然后应该判断其属性值是否相等
 *     Object类的equals()只比较两个对象的地址值是否相同,而String、Date、包装类等都重写
 *     了父类Object的equals()方法,比较的是对象的“实体内容”(属性值)
 */

public class EqualsTest {
	
	public static void main(String[] args) {
		int i = 10;
		int j = 10;
		double d = 10.0;
		boolean b = true;
		char c = 10;
		System.out.println(i == j); // true
		System.out.println(i == d); // true,自动类型提升
		// System.out.println(i == b); // 报错,布尔类型不能参与算术运算
		System.out.println(i == c); // true
		
		String str1 = new String("hello");
		String str2 = new String("hello");
		System.out.println(str1 == str2); // false。两个不同的对象
		System.out.println("******************");
		Customer cust1 = new Customer("Tom", 12);
		Customer cust2 = new Customer("Tom", 12);
		
//	    public boolean equals(Object obj) { // 多态。Customer继承了Object中的equals()方法
//        return (this == obj); // 只是比较两个引用的地址值是否相同
//    }
		System.out.println(cust1.equals(cust2)); // false
		
		// String和Date中重写了Object中的equals()方法,
		// 查看源码,比较的不再是两个对象的地址值,而是“实体内容”
		System.out.println(str1.equals(str2)); // true
		Date date1 = new Date(23432423424L);
		Date date2 = new Date(23432423424L);
		System.out.println(date1.equals(date2)); // true
	}
}

class Customer {
	String name;
	int age;
	
	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
	}
}
    重写自定义类Customer中的equals()方法

package com.atguigu.java1;

/*
 * 通常情况下要使用自定义类中的equals()时,也希望它比较的是两个对象的“实体内容”,
 * 即要比较我们关心的主要属性,所以就要对object中的equals()进行重写
 */

public class EqualsTest1 {
	
	public static void main(String[] args) {
		Customer cust1 = new Customer("Tom", 12);
		Customer cust2 = new Customer("Tom", 12);
		System.out.println(cust1.equals(cust2)); // true
	}
}

class Customer {
	String name;
	int age;
	
	public Customer(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public boolean equals(Object obj) {
		// String的equals()方法:
		// 1,先判断两个引用是否指向同一对象
		// 2,判断传入的对象是否是String的一个实例
		// 3,将传入的Object类型对象强转为String,String类型底层实际是用char类型的数组存放字符串的
		// 4,比较两个对象中char类型数组的长度是否相等
		// 5,逐一比较两个char类型数组每个元素的值
		if(this == obj) { // 传入的就是当前对象
			return true;
		}
		
		if(obj instanceof Customer) { // 传入的是否为Customer的一个实例
			Customer cust = (Customer)obj; // 强转
//			if(this.age == cust.age && this.name.equals(cust.name)) { // 判断属性是否相等,因为name是String类型,
							// 所以要用String的equals()方法,如果用==,又变为比较两个引用存储的地址值了
//				return true;
//			}else {
//				return false;
//			}
			return this.age == cust.age && this.name.equals(cust.name);
		}else {
			return false;
		}
	}
}
    实际开发中,可以直接生成要重写的equals()方法

day13-面向对象(中)_面向对象章节

    生成的equals()方法

public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Customer other = (Customer) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
  }

 

6,总结equals()与==

day13-面向对象(中)_面向对象章节_02

 

7,toString()的使用

package com.atguigu.java1;

import java.util.Date;

/*
 * 在Object类中定义的默认的toString()方法返回当前对象的内存地址值,
 *     当println()输出一个对象的引用时,实际上调用了当前对象的toString()方法,
 *     调用过程是println()->String.valueOf()->obj.toString()
 * 像String、Date、包装类都重写了Object的toString(),在通过对象调用toString()
 *     时,返回“实体内容”,即希望看到的对象属性
 */

public class ToStringTest {
	
	public static void main(String[] args) {
		Customer1 cust1 = new Customer1("Tom", 12);
		// Object中的toString()方法,返回当前对象的类名@内存地址值,这个内存地址值并不是真实的内存地址,而是相当于JVM中的
//	    public String toString() {
//	        return getClass().getName() + "@" + Integer.toHexString(hashCode());
//	    }
		// 没有重写toString()的前提下
		System.out.println(cust1.toString()); // com.atguigu.java1.Customer1@15db9742
		System.out.println(cust1); // com.atguigu.java1.Customer1@15db9742,与调用toString()的结果相同
		
		String str = new String("MM");
		System.out.println(str); // MM
		Date date = new Date(23454353L);
		System.out.println(date.toString()); // Thu Jan 01 14:30:54 CST 1970
	}
}

class Customer1 {
	String name;
	int age;
	
	public Customer1(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
//	public String toString() { // 自动生成的toString()。在需要时重写,输出希望看到的内容
//		return "Customer1[name = " + name + ", age = " + age + "]";
//	}
}

 

8,Object类综合练习

    父类

package com.atguigu.java1;

public class GeometricObject {
	protected String color;
	protected double weight;
	
	public GeometricObject() {
		super();
		this.color = "white";
		this.weight = 1.0;
	}

	public GeometricObject(String color, double weight) {
		super();
		this.color = color;
		this.weight = weight;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}
}
    子类

package com.atguigu.java1;

public class Circle extends GeometricObject {
	private double radius;
	
	public Circle() {
		super();
		radius = 1.0;
	}

	public Circle(double radius) {
		super();
		this.radius = radius;
	}
	
	public Circle(double radius, String color, double weight) {
		super(color, weight);
		this.radius = radius;
	}

	public double getRadius() {
		return radius;
	}

	public void setRadius(double radius) {
		this.radius = radius;
	}
	
	public double findArea() {
		return 3.14 * radius * radius;
	}
	
	public boolean equals(Object obj) { // 如果两个Circle对象的半径相等,就认为这两个对象相等
		if(this == obj) {
			return true;
		}
		if(obj instanceof Circle) {
			Circle c = (Circle)obj;
			return this.radius == c.radius;
		}
		return false;
	}

	public String toString() {
		return "Circle [radius=" + radius + "]";
	}
}
    测试

package com.atguigu.java1;

public class CircleTest {
	
	public static void main(String[] args) {
		Circle circle1 = new Circle(2.3);
		Circle circle2 = new Circle(2.3, "white", 2.0);
		// 比较两个String的引用数据类型是否相等
		System.out.println("颜色是否相同:" + circle1.getColor().equals(circle2.getColor()));
		System.out.println("半径是否相等:" + circle1.equals(circle2));
		System.out.println(circle1);
		System.out.println(circle2.toString());
	}
}

 

9,单元测试方法的使用

    单元测试:只单独的测试某段代码

day13-面向对象(中)_面向对象章节_03

    接着选择JUnit->finish,可以看到在当前工程下加入了一个叫JUnit4的包

package com.atguigu.java1;

/*
 * 创建Java类,进行单元测试
 * 要求:此类是公共的;提供公共的无参构造器;在类中声明单元测试方法,
 *     该方法是公共的,没有返回值和形参,在方法的上面加上注解@Test,
 *     导入org.junit.Test
 * 在方法中测试写完的相关代码:双击选择方法名,右键Run as->Junit Test。
 *     在JUnit窗口下,出现绿条表示执行正常,红条表示出现异常
 *     想测试哪个方法就点哪个方法
 * 实际开发中可以直接在一个类中写单元测试方法:@Test+方法,按照报错的提示
 *     导入包和类
 */

import org.junit.Test;

public class JUnitTest {
	int num = 10;
	@Test
	public void testEquals() {
		String s1 = "MM";
		String s2 = "MM";
		System.out.println(s1.equals(s2));
		System.out.println(num);
	}
	
	@Test
	public void testToString() {
		String s = "MM";
		System.out.println(s.toString());
	}
}

 

10,包装类

    为了让8中基本数据类型也可以具有类的特征,就有了包装类。以int类型来说,将一个int类型的变量包含在Integer类中,此时就可以表现封装、继承、多态性了,但这个类最核心的还是int类型的属性
    有了包装类,Java才算是纯粹的面向对象

day13-面向对象(中)_面向对象章节_04

    基本数据类型和包装类之间的转化

package com.atguigu.java1;

import org.junit.Test;

public class WrapperTest {
	// 基本数据类型-->包装类:调用对应包装类的构造器
	@Test
	public void test1() {
		int num1 = 10;
		Integer in1 = new Integer(num1); // in1是一个将10包装起来的对象
		System.out.println(in1.toString()); // 10。Integer重写了toString(),输出“实体内容”
		
		Integer in2 = new Integer("123"); // 可以传入一个字符串,但必须是整数的,如果是123ab就会异常
		System.out.println(in2.toString());
		
		Float f1 = new Float(12.3f);
		Float f2 = new Float(12.3); // 传入的是一个double类型
		System.out.println(f1);
		System.out.println(f2); // 省略了toString()
		
		// Boolean的底层是:return ((s != null) && s.equalsIgnoreCase("true"));
		// 只要传入的对象不为空且是大小写格式的“true”,就返回true
		Boolean b1 = new Boolean(true);
		Boolean b2 = new Boolean("TrUe");
		System.out.println(b2); // true
		Boolean b3 = new Boolean("true123");
		System.out.println(b3); // false
	}
}

class Order1 {
	boolean isMale; // 默认初始化值false
	Boolean isFemale; // 默认初始化值null
}
package com.atguigu.java1;

import org.junit.Test;

public class WrapperTest1 {
	// 包装类-->基本数据类型:调用包装类的XXXValue()
	// 一些方法的形参是引用类型的,此时基本数据类型需要转换为包装类
	// 包装类不能直接做算术运算,此时包装类需要转换成基本数据类型
	@Test
	public void test2() {
		Integer in1 = new Integer(12);
		int i1 = in1.intValue();
		System.out.println(i1 + 1);
		
		Float f1 = new Float(12.3);
		float f2 = f1.floatValue();
		System.out.println(f2 + 1.2);
	}
}
    自动装箱和自动拆箱

package com.atguigu.java1;

import org.junit.Test;

public class WrapperTest2 {
	// JDK5.0新特性:自动装箱和自动拆箱
	@Test
	public void test3() {
		int num = 10;
		Integer in1 = num; // 自动装箱,将一个int类型变量直接赋值给Integer类型
						// 引用。基本数据类型-->包装类的转换自动完成
		int num1 = in1; // 自动拆箱。包装类-->基本数据类型的转换自动完成
	}
}
    有了自动装箱和拆箱,可以把基本数据类型和包装类看作一个整体
    与String之间的相互转换

package com.atguigu.java1;

import org.junit.Test;

public class WrapperTest3 {
	// 基本数据类型/包装类-->String
	@Test
	public void test4() {
		int num1 = 10;
		// 方式1:连接运算
		String str1 = num1 + "";
		// 方式2:
		float f1 = 12.3f;
		String str2 = String.valueOf(f1); // "12.3"
		Double d1 = new Double(12.4);
		String str3 = String.valueOf(d1);
	}
	
	// String-->基本数据类型/包装类
	@Test
	public void test5() {
		String str1 = "123";
		// 错误情况
		// int num1 = (int)str1;
		// Integer in1 = (Integer)str1;
		int num1 = Integer.parseInt(str1);
		String str2 = "123a";
		int num2 = Integer.parseInt(str2); // 抛出异常
		
		String str3 = "true";
		boolean b1 = Boolean.parseBoolean(str3);
		String str4 = "true1";
		boolean b2 = Boolean.parseBoolean(str4); // false,不会抛异常
	}
}
    只需要记住自动装拆箱、valueOf()、parseXxx()即可

day13-面向对象(中)_面向对象章节_05

    练习:

package com.atguigu.java2;

import org.junit.Test;

public class InterviewTest {
	@Test
	public void test1() {
		Object o1 = true ? new Integer(1) : new Double(2.0); // 使用三元运算符必须保证结果是同一类型,所以1被提升为1.0
		System.out.println(o1); // println调用o1的toString(),而toString()被Integer重写过。输出1.0,而不是1
	}
	
	@Test
	public void test2() {
		Object o2;
		if(true)
			o2 = new Integer(1);
		else
			o2 = new Double(2.0);
		System.out.println(o2); // 输出1,在if-else中没有规定统一类型
	}
	
	@Test
	public void test3() {
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		System.out.println(i == j); // false
		
		Integer m = 1;
		Integer n = 1;
		System.out.println(m == n); // true。说明m和n指向的是同一个对象
		// 这是因为在Integer中定义了一个静态的内部类IntegerCache,用作缓存的作用。
		// 在IntegerCache内部定义了一个静态的Integer类型的数组,保存了-128~127
		// 之间所有整数的的Integer类型对象。当使用自动装箱时,给Integer类型
		// 的引用赋值在-128~127之间时,直接用数组中已有的对象赋值,不用再new对象
		Integer x = 128;
		Integer y = 128; // 而超出127的则是要new对象,所以这是new了两个对象
		System.out.println(x == y); // false
	}
}
package com.atguigu.java2;

import java.util.Scanner;
import java.util.Vector;

public class ScoreTest {
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		
		// 创建Vector对象,可以当作数组使用
		Vector v = new Vector();
		
		int maxScore = 0;
		for(;;) {
			System.out.println("请输入学生成绩(输入负数代表结束)");
			int score = scan.nextInt();
			if(score < 0) {
				break;
			}
			if(score > 100) {
				System.out.println("输入有误");
				continue;
			}
			// 向Vector对象中添加元素
			// JDK5.0之前
//			Integer inScore = new Integer(score);
//			v.addElement(inScore); // 形参是Object类型,多态
			v.addElement(score); // 自动装箱
			if(maxScore < score) {
				maxScore = score;
			}
		}
		
		char level;
		for(int i = 0 ; i < v.size(); i++) {
			Object obj = v.elementAt(i);
			// JDK5.0之前
//			Integer inScore = (Integer)obj;
//			int score = inScore.intValue();
			int score = (Integer)obj; // 自动拆箱,还可以写成int score = (int)obj;
			
			if(maxScore - score <= 10) {
				level = 'A';
			}else if(maxScore - score <= 20) {
				level = 'B';
			}else if(maxScore - score <= 30) {
				level = 'C';
			}else {
				level = 'D';
			}
			System.out.println("student-" + i +
					" score is " + score + ",level is " + level);
		}
	}
}