面向对象编程(一):类与对象 实训答案
一、理解面向对象编程
1、下列关于面向对象编程的说法,正确的有:
A、只要使用Java语言解决问题,就是在使用面向对象编程思想解决问题。
B、对象是个体,从一组具有相同属性和类似行为的个体中可以抽象类,以后凡是要创建对象,只需要根据类来创建,而不需要从0开始创建,这体现了面向对象编程。
C、Java类的定义体现了封装性。
D、接口是面向对象编程的一大特性
E、要使用面向对象编程思想求解问题,首先要明确:待求解的问题涉及到的对象有哪几类,这些对象之间的相互关系如何。
F、不具备继承特性的语言,不是真正意义上的面向对象编程语言。
G、多态性就是一个对象存在多种不同的状态。
2、以下关于面向对象编程的说法,正确的有
A、面向对象编程是一种编程架构,它以类的设计为中心。
B、面向对象编程中,对象和实例通常指的是一个意思。
C、基于面向对象的思考问题的方式,是比基于面向过程的思考问题的方式更高层的抽象方式。
D、一个类是对一批对象的抽象
E、面向对象编程的主要工作是设计出可高度重用的类,由于程序中所需要的某些类往往已经由别人“造好了”,可以直接拿来用,因此,用好他人开发好的类,可以显著提高开发效率
3、关于面向对象编程的三大特性的说法,正确的有
A、类和对象体现抽象与具体的关系,是封装性的表现
B、封装性使得我们在使用类时,只需要关注它所提供的外部接口,而无需深入了解其内部实现。
C、继承性使得可以在已有的“类”的基础上,以最少的代码创建新的类。
D、一个类中可以定义多个名称相同,参数类型不同的方法,这是多态性的唯一表现。
答案:
1.BCEF
2.ABCDE
3.BC
二、类的定义与对象的创建
程序描述 输入三角形的三个边的边长,求三角形的面积。
本程序由两个源文件构成: Test.java:主类定义 Triangle.java:三角形类的定义 其中,Test.java中的代码如下:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入三角形的三个边的长度:");
double sideA = sc.nextDouble();
double sideB = sc.nextDouble();
double sideC = sc.nextDouble();
Triangle t=new Triangle(sideA,sideB,sideC);
System.out.printf("边长为(%.2f,%.2f,%.2f)的三角形面积为%.3f"
,t.getSideA(),t.getSideB(),t.getSideC()
,t.getArea());
sc.close();
}
}
Triangle.java
import java.lang.Math;
class Triangle{
private double SideA;
private double SideB;
private double SideC;
private double Area;
public Triangle() {
}
public Triangle(double sideA, double sideB, double sideC) {
SideA = sideA;
SideB = sideB;
SideC = sideC;
}
public double getSideA() {
return SideA;
}
public void setSideA(double sideA) {
SideA = sideA;
}
public double getSideB() {
return SideB;
}
public void setSideB(double sideB) {
SideB = sideB;
}
public double getSideC() {
return SideC;
}
public void setSideC(double sideC) {
SideC = sideC;
}
public double getArea() {
Area = area(SideA,SideB,SideC);
return Area;
}
public void setArea(double area) {
Area = area;
}
public double area(double sideA ,double sideB,double sideC){
double p = (sideA+sideB+sideC)/2;
double area = Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC));
return area;
}
}
三、理解构造方法
1、以下关于构造方法的说法,正确的有:
A、构造方法是使用new创建对象时调用的方法,通常用于对一个类的实例的各个数据成员进行初始化。
B、在一个类的定义中,若没有包含构造方法的显式定义,则这种类是没有构造方法的。
C、一个Java类至少有一个构造方法,当开发者在定义类是没有提供构造方法,Java系统会自动提供默认的构造方法。
D、构造方法返回值为void
E、使用new创建一个类对象的前提条件是,这个类已经创建好了。
F、一个类的类体中可以定义多个构造方法,但一个类的实例在创建时,只能选择其中的一个构造方法加以调用。
对于构造方法的理解,正确的有
A、构造方法在外在表现形式上的特殊地方在于它与类名相同,由于其返回值约定为void,因此,通常定义时,省略void。
B、构造方法是对象创建时调用的方法,通常用于执行对象内部的数据成员的一些初始化操作。
C、若定义一个类时,没有提供构造方法的定义,则这个类是没有构造方法的类。
D、只要在一个类中定义了一个构造方法,Java编译器便不会提供默认构造方法。
答案:
1.ACDEF
2.ABD
四、构造方法的运用
任务描述
本关任务:编写一个程序,使程序的输出满足测试结果的要求。
程序包含两个文件:
Test4.java:主类定义文件
MyClass.java:MyClass类的定义文件
Test4.java中的代码如下:
public class Test4 {
public static void main(String[] args) {
MyClass m=new MyClass();
m.showMemberInfo();
m=new MyClass(24);
m.showMemberInfo();
}
}
class MyClass
public class MyClass {
public int m1=2;
public void showMemberInfo() {
System.out.printf("m1=%d\n",m1);
}
//begin
public MyClass(){
System.out.print("object constructing...\nconstructing finished!\n");
}
public MyClass(int m1){
this.m1 = m1;
}
//end
}
五、根据要求完成类的定义
任务描述
本关任务:本程序可实现两个整数的值的交换。主类(Test)的代码已经给出,你只需要完成所需的类中的代码,使主类可以正常运行。以下是主类(Test.java)中的代码:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int a1=sc.nextInt();
int b1=sc.nextInt();
MyNumber numA=new MyNumber(a1);
MyNumber numB=new MyNumber(b1);
System.out.printf("a1=%d,b1=%d\n",numA.getNumber(),numB.getNumber());
MyNumber.swap(numA,numB);
System.out.printf("a1=%d,b1=%d", numA.getNumber(),numB.getNumber());
sc.close();
}
}
相关知识
为了完成本关任务,你需要掌握:1.类的方法和对象方法,2.对象变量是对内存中的对象的引用。
测试说明
平台会对你编写的代码进行测试:
测试输入:4 91
预期输出:
a1=45,b1=67
a1=67,b1=45
这里要从内存上理解,每次new生成的对象存放在不同的地址中,需要调用
public class MyNumber {
private int number;
public MyNumber() {
}
public MyNumber(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public static void swap(MyNumber a, MyNumber b){
int temp = a.getNumber();
a.setNumber(b.getNumber());
b.setNumber(temp);
}
}
六、任务描述
本关任务:编写一个能进行矩阵乘法运算的程序。
A×B,当A的列数和B的行数相同时,能进行矩阵运算。
本程序的主类源文件(Test.java)已经创建好了,其中代码如下:
import java.util.Scanner;
public class Test {
public static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("请输入矩阵A的行列数(空格间隔)");
int rowNum=sc.nextInt();
int colNum=sc.nextInt();
System.out.println("请逐行输入矩阵A的元素值(每输入一行回车一次,同一行相邻元素用空格分隔)");
double[][] arrA = inputArray(rowNum, colNum);
System.out.println("请输入矩阵B的行列数(空格间隔)");
rowNum=sc.nextInt();
colNum=sc.nextInt();
System.out.println("请逐行输入矩阵B的元素值(每输入一行回车一次,同一行相邻元素用空格分隔)");
double[][] arrB = inputArray(rowNum, colNum);
Matrix matA = new Matrix(arrA);
Matrix matB = new Matrix(arrB);
// 执行矩阵乘法,关于矩阵乘法的定义,请参考线性代数相关知识或百度查询
Matrix matC = matA.multiply(matB);
// 输出矩阵乘法的结果,注:这里实际上隐含着调用matC.toString(),因此,Matrix要定义toString方法,返回矩阵的字符串表示
System.out.println(matC);
Test.sc.close();
}
/**
* 输入一个二维数组,并返回这个数组的引用
*
* @param row 行数
* @param col 列数
* @return 数组的引用
*/
public static double[][] inputArray(int row, int col) {
double[][] a = new double[row][col];
for (int r = 0; r < row; r++) {
for (int c = 0; c < col; c++) {
a[r][c] = sc.nextDouble();
}
}
return a;
}
}
相关知识
为了完成本关任务,你需要掌握:1.类的定义2.类的成员和对象的成员。
编程要求
在右侧编辑器补充代码。
测试说明
平台会对你编写的代码进行测试,以下是某个用例下的测试结果画面:
请输入矩阵A的行列数(空格间隔)
3 2
请逐行输入矩阵A的元素值(每输入一行回车一次,同一行相邻元素用空格分隔)
1 2
3 4
5 6
请输入矩阵B的行列数(空格间隔)
2 2
请逐行输入矩阵B的元素值(每输入一行回车一次,同一行相邻元素用空格分隔)
1.4 45
34 0
[
[69.400 45.000 ]
[140.200 135.000 ]
[211.000 225.000 ]
]
Matrix.java
public class Matrix {
public double [][] arr;
public Matrix() {
}
public Matrix(double[][] arr) {
this.arr = arr;
}
public Matrix multiply(Matrix matB){
Matrix matC = new Matrix();
matC.arr = new double[this.arr.length][matB.arr[0].length];
for(int i=0;i<this.arr.length;i++){
for(int j=0;j<matB.arr[0].length;j++){
matC.arr[i][j] = 0;
for(int k=0;k<this.arr[0].length;k++){
matC.arr[i][j] += this.arr[i][k]*matB.arr[k][j];
}
}
}
return matC;
}
public String toString(){
String result = "[\n";
for(int i=0;i<arr.length;i++){
result+="[";
for(int j=0;j<arr[0].length;j++){
result+=arr[i][j]+"00 ";
}
result += "]\n";
}
result+="]\n";
return result;
}
}
七、类之间的关系的UML图描述
1、有关复杂的类的实现,说法正确的有
A、复杂的类对象分解为简单的类对象的组合,这是实现复杂的类的方法之一
B、如果一些类之间存在明显的继承关系,就可以使用继承来实现类的设计,这也是一种实现复杂的类的方法。
C、分解与组合的方法,在代码上的表现往往就是:某个类的一些数据成员的数据类型为另外一些类
D、我们要使用Java类库,只需要知道库中的类的用法,没必要知道这个类和其他类的关系。
2、有关类的关系及其UML图的表示,说法正确的有
A、UML图,仅用于描述一个类和他类之间的关系
B、UML图,只针对Java语言,对其他编程语言的开发者,没有意义。
C、继承关系、实现关系从代码外部接口就可以看出来,而组合、聚合、关联这三种关系,如果没有清晰的UML图,仅从类的外部接口代码,不好相互区分。
D、类A组合于B,意味着,A类的对象创建后,其中包含着B类对象的创建,当A类对象被垃圾回收器回收时,其内部的B类对象也自动会被回收。
E、关联关系比依赖关系要强,A关联于B,则A的定义中包含了B类的数据成员。A依赖于B,仅表明A中的某个方法的定义中用到了B。
答案:
1.ABC
2.CDE
八、包的定义与使用
1、下列关于Java包的说法,不正确的有
A、Java标准库、第三方的商业类库,都是按包的方式来管理众多的类
B、Java标准库中的某些类,如Math类,在使用时,不必使用import语句导入,是因为这些类所在的包为匿名包
C、开发大型应用程序时,利用包的机制管理好大量自定义的类,是一个值得推荐的做法
D、用户声明的包可以分层次,例如“cn.guet”是一个具有2个层级的包,它要求在应用程序顶层目录下有对应的二级子目录:“cn\guet”,这个包下的类,例如cn.guet.ClassA,编译后对应的class文件,则不一定非要放到guet子目录下。
E、同一个包中的类所在的源文件没有必要存入同一个目录,只需要文件开头有相同的package声明语句就可以了。
2、下列关于Java包的用法,不正确的有
A、多个源文件中开头有声明语句”package imagan.file;”,表示这些源文件中定义的类都隶属于imagan.file这个包。
B、源文件“ClassA.java”和源文件“ClassB.java”中都有一条声明语句“package guet.myclass;”,且ClassA关联于ClassB,则在ClassA.java文件中必须有import guet.myclass.ClassB或 import guet.myclass.*语句。
C、已知类classA位于cn包中,而classB位于cn.test包中,则在classA的定义中,要引用classB,可以使用“import test;”语句(test前面的cn.可以省略)。
D、在某个源文件中要使用位于不同包中的两个类,而这两个类的类名是相同的,为了向编译器指明当前要使用的类,有必要在类名前加包名前缀。
3、程序中要用到第三方Java扩展库中的某个类DemoClass,该类位于包guet.imagan中,则在需要用到该类的源文件中可以加入的语句,正确的有:
A、
package guet.imagan.DemoClass;
B、
import guet.imagan.*;
C、
from guet.imagan import DemoClass;
D、
import guet.imagan.DemoClass;
答案:
1.BDE
2.BC
3.BD
九、类的外部访问权限的理解
1、下列关于Java类的外部访问权限的说法,正确的有
A、外部访问权限的合理设计,有利于类使用的安全性和方便性
B、外部访问权限的控制,是通过public. protected. private等几个关键字来设置的
C、某个类DemoClass的名称前没有加public关键字,则其他类都不能直接引用DemoClass
D、加了private关键字的方法成员或数据成员,是不能在该成员所在的类体以外任何地方直接访问的,连当前类的子类也不能直接访问
2、要设计一个名为“MyClass”的类,它包含数据成员“member1”和“member2”、方法成员“func1”和“func2”,希望:任何其他类(包括子类)都不能直接读写“member1”,只有同一个包中的类可以直接读写“member2”,子类不能继承“member2”;任何其他类都可以调用“func1”,而只有同一个包中的类以及MyClass的子类可以直接调用“func2”,则“MyClass”、“member1”、“member2”、“func1”、“func2”前面的权限控制关键字分别为
A、
public, 不加关键字,private,public, protected
B、
public, private, 不加关键字,protected, public
C、
public, protected, 不加关键字,public, private
D、
public, private, 不加关键字,public, protected
答案:
1.ABD
2.D
十、基本数据类型的类包装
1、public class Test{
public static void swap(Integer a,Integer b) {
Integer c=a;
a=b;
b=c;
}
public static void main(String[]args){
Integer a=3;
Integer b=4;
swap(a,b);
System.out.println(a+”,”+b);
}
}
请问上述代码的执行结果怎样?(请注意,通过这个例子,要总结出基本数据类型进行类封装后,对象变量到底表示的是值,还是对象的引用)。(A)
A、
3,4
B、
3,3
C、
4,4
D、
4,3
2、以下Java代码正确的有
A、
Int a=5;
B、
Bool t=true;
C、
Byte a=123;Char b=‘A’;
D、
double a=10.34; Double b=a;
E、
Float a=3.1415f;
3、以下有关字符串与数值间的相互转换的代码,正确的有
A、
int e=Integer.valueOf(“1234”);
B、
Float e= Float.valueOf(“1234”);
C、
String s1=4;
D、
String s1=String.valueOf(4);
E、
Double a=4.6;String s1=a.toString();
答案:
1.A
2.DE
3.ABDE
十一、带可变参数的方法
任务描述
本关任务:根据程序的提示,补充完整代码。
相关知识
为了完成本关任务,你需要掌握:1.了解什么是可变参数2.如何使用可变参数。
编程要求
根据提示,在右侧编辑器补充代码,计算并输出任意多个输的均值。
public class Test {
public static void main(String[] args) {
//求两个数的均值
System.out.printf("%.2f\n",Test.getAve(2,3));
//求三个数的均值
System.out.printf("%.2f",Test.getAve(2,3,4));
}
//请在1、2处补充代码,不允许在其他地方修改或添加代码
public static double getAve(int ... x) {
double sum = 0;
for(int i = 0;i<x.length;i++){
sum = sum + x[i];
}
return sum/x.length;
}
}
1.这里给出我一些对new的理解,当你new之后,生成的对象是在不同的地址的,通过带参构造的new,调用同一个类的不同构造对象,数据不同。
2.构造可以理解为一个箱子,保护里面的数据,里面的参数用private进行保护,调用的时候要用get,设置时用set。
3.在idea中可以使用快捷键生成
Alt+Insert
第一个是构造函数的快捷生成
第四个是get和set的快捷生成
第六个是toString()方法,要改自己改
(单纯分享,希望过了的同学能在老师答疑时间去把不懂的地方问清楚,用辅导员的话来说,都是成年人了!想想自己以后工作问题,或者说,你的未来。我们客观一点,来到这里,是你曾经努力或者不努力的结果,但现在,我希望我们专业的同学能离开宿舍,离开小视频,离开峡谷,去图书馆,去四创,去那些能让你学习的地方。我们反思一下,我们为什么选到这个专业,或者说你本来就喜欢这个专业,觉得前景好,亦或许你是成绩不够,被迫选到这个,但我告诉你,学校教给你的是专业,出去人家要的是专长,其实都差不多的,你的未来,在你的手上,我们要用未来5年后的自己的眼光来看现在的自己,你努力了吗?不要跟我说什么你毕业不干这行,你以为全部考试过了你就能干这行?但至少,拿到毕业证和学位证是你现在该干的事,不是吗?)
在此声明,我不是什么厉害的人,只是一个突然后悔曾经或者说高中不努力的普通人,写这些话也只是因为希望能有更多一起努力的人罢了,或许会有些非本校的朋友或者非本专业的朋友看到这些,希望不要取笑,毕竟,我们都是在为梦想不断努力奋斗的人,难道不是吗?