JavaSE面向对象编程下练习题

JavaSE面向对象编程下练习题

  • 接口
  • 内部类
  • 抽象类与抽象方法
  • final关键字
  • 代码块
  • 参考资料

接口

选择题

1 下面关于接口的说法中不正确的是

  • A 接口中所有的方法都是抽象的 // JDK7及以前 接口中只可以定义抽象方法 JDK8及以后 接口中可以定义 抽象方法,静态方法和 默认方法
  • B 接口中所有的方法都是public访问权限
  • C 子接口继承父接口所用的关键字是implements // extends
  • D 接口是Java中的特殊类,包含常量和抽象方法

2 Java语言接口间的继承关系是 B

  • A 单继承 // 类的继承的单继承,但是可以多层继承
  • B 多继承
  • C 不能继承
  • D 不一定
interface AA{
	void method1();
}
interface BB{
	void method2();
}
interface CC extends AA,BB{
	
}

3 一个类实现接口的情况是 A

  • A 一次可以实现多个接口
  • B 一次只能实现一个接口
  • C 不能实现接口
  • D 不一定

Java类可以实现多个接口,格式:class AA extends BB implements CC,DD,EE {}

填空题

1 (interface) 是声明接口的关键字,可以把它看成一个特殊类。接口中的数据成员默认的修饰符是(public static final),接口中的成员方法默认的修饰符是(public abstract)。

2 如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须 (重写) 该接口的所有抽象方法;如果实现某接口的类是abstract的抽象类,则它可以 (继承) 该接口所有的方法。但是对于这个抽象类任何一个非抽象的子类而言,它们父类所实现的接口中的所有抽象方法以及自身所实现接口中的抽象方法都必须有实在的 (重写方法)

补全代码

interface Inter {
	void show(int a, int b);

	void func();
}

class Demo {
	public static void main(String[] args) {
		// 补足代码;调用两个函数,要求用匿名内部类
		// 匿名类 没有显式声明的类去实现此接口 
		Inter in = new Inter() {
			public void show(int a, int b) {
				System.out.println("a + b = " + (a+b));
			}

			public void func() {
				System.out.println("自信即巅峰!");
			}
		};

		in.show(4, 5);
		in.func();

	}
}

简答题

1 abstract class 和interface 有什么区别?

声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口

(现在并没有多少理解,等以后考古回来再看)

2 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?

接口可以继承接口 ,而且可以多继承

抽象类可以实现(implements)接口

抽象类可继承实体类,但实体类必须不能是如下两种情况之一:

  • final修饰符修饰的类是不能的
  • 如果此实体类有且仅有私有的构造函数也是不能的

写出程序结果

interface A{}

class B implements A{
    public String func(){
        return "func";
    }
}

class Demo{
    public static void main(String[] args){
        A a=new B();
        System.out.println(a.func());
    }
}

编译失败:因为A接口中并未定义func方法

编译题

1 编一个程序,包含以下文件
(1) Shape.java文件,在该文件中定义接口类Shape,该接口在shape包中。
属性:PI。
接口:求面积的方法area()
(2) Circle.java文件,在该文件中定义圆类Circle,该类在circle包中,实现Shape接口类。
属性:圆半径radius。
方法:构造器;实现求面积方法area();求周长方法perimeter()。
(3) Cylinder.java文件,在该文件中定义圆柱体类Cylinder,该类在cylinder包中,继承圆类。
属性:圆柱体高度height。
方法:构造器;求表面积方法area();求体积方法volume()
(4) X5_3_6.java文件,在该文件中定义主类X5_3_6,该类在默认包中,其中包含主方法main(),在主方法中创建两个圆类对象cir1和cir2,具体尺寸自己确定,并显示圆的面积和周长;再创建两个圆柱体类的对象cy1和cy2,具体尺寸自己确定,然后分别显示圆柱体cy1和cy2的底圆的面积和周长以及它们各自的体积和表面积

[编程分析] 本题主要考察接口、包、继承、封装等问题

package com.atguigu.shape;

public interface Shape {

    public static final double PI = 3.14;
    public abstract void area();
}

package com.atguigu.circle;

import com.atguigu.shape.Shape;

public class Circle implements Shape {

    private double radius;

    public Circle(){

    }

    public Circle(double radius){
        this.radius = radius;
    }
    public double getRadius(){
        return this.radius;
    }

    public void setRadius(double radius){
        this.radius = radius;
    }

    public void perimeter(){
        System.out.println("圆周长为" + (2*PI*radius));
    }

    public void area(){
        System.out.println("圆面积为" + (PI*radius*radius));
    }
}

package com.atguigu.cylinder;

import com.atguigu.circle.Circle;

public class Cylinder extends Circle {

    private double height;

    public Cylinder(){

    }

    public Cylinder(double radius,double height){
        super(radius);
        this.height = height;
    }

    public double getHeight(){
        return this.height;
    }

    public void setHeight(double height){
        this.height = height;
    }

    public void area(){
        System.out.println("圆柱表面积为" + (2*PI*getRadius()*height +
                2*PI*getRadius()*getHeight()));
    }

    public void volume(){
        System.out.println("圆柱的体积为" + (PI*getRadius()*getHeight()*height));
    }
}

package com.atguigu;

import com.atguigu.circle.Circle;
import com.atguigu.cylinder.Cylinder;

public class X5_3_6 {
    public static void main(String[] args) {
        Circle cir1 = new Circle(5.0);
        Circle cir2 = new Circle(4.2);

        cir1.area();
        cir1.perimeter();

        cir2.area();
        cir2.perimeter();

        Cylinder cy1 = new Cylinder(3.0,5.0);
        Cylinder cy2 = new Cylinder(2.4,4.0);
        cy1.area();
        cy1.volume();

        cy2.area();
        cy2.volume();
    }
}

2 请使用接口编码实现如下需求

乐器(Instrument)分为:钢琴(Piano)、小提琴(Violin).各种乐器的弹奏( play )方法各不相同。编写一个测试类InstrumentTest,要求:编写方法testPlay,对各种乐器进行弹奏测试。要依据乐器的不同,进行相应的弹奏。在main方法中创建不同的乐器对象,通过testPlay的弹奏测试方法进行测试。

package com.atguigu.exer8;

public interface Instrument {
    public abstract void play();
}

package com.atguigu.exer8;

public class Test {
    public static void main(String[] args) {
        InstrumentTest t1 = new InstrumentTest();

        t1.testPlay(new Piano());
        t1.testPlay(new Violin());
    }
}

class InstrumentTest{
    public void testPlay(Instrument ins){
        System.out.println("准备!");

        ins.play();

        System.out.println("结束!");
    }
}

class Piano implements Instrument{
    public void play(){
        System.out.println("钢琴弹奏");
    }
}



class Violin implements Instrument{
    public void play(){
        System.out.println("小拉琴拉起");
    }
}


内部类

选择题

public class OuterClass { 
  private double d1 = 1.0; 
    //insert code here 
}

You need to insert an inner class declaration at line 3. Which two inner class declarations are valid?(Choose two.)

A. class InnerOne{
     public static double methoda() {return d1;}
   } 
B. public class InnerOne{
     static double methoda() {return d1;}
   }

静态内部类可以有静态成员,而非静态内部类则不能有静态成员。 故 A、B 错

static class InnerOne{
     protected double methoda() {return d1;}
   } 

静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;return d1 出错。 故 D 错

C. private class InnerOne{
     double methoda() {return d1;}
   }
E. abstract class InnerOne{
     public abstract double methoda();
   }

非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确答案为C、E

(剩下的题不做了 内部类这里学的太垃圾了 )

抽象类与抽象方法

抽象类和抽象方法之间的关系

定义抽象类和抽象方法的关键字是(abstract)。抽象类中(可以)(可以/不可以)有抽象方法,(可以)(可以/不可以)有普通方法(可以)(可以/不可以)有属性;一个类中定义了抽象方法,那这个类(必须)(必须/不必须)用abstract修饰,即抽象类。

判断题

abstract class Name {
   private String name;
   public abstract boolean isStupidName(String name) {}
}

这有何错误?
答:abstract修饰方法:抽象方法只有方法的声明,没有方法体
所以 abstract method必须以分号结尾,且不带花括号。

是否可以通过编译?

abstract class Something {
   private abstract String doSomething ();
}

答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的,怎么可以用private把abstract method封锁起来呢? (同理,abstract method前不能加final)。

编程题

定义一个抽象类Person,有name,age,sex三个属性,创建构造函数,给这三个属性赋值,重写打印描述信息方法,打印三个属性值;这个类中有两个抽象方法work和hello;定义两个子类Teacher,Student;教师的work实现是:教书育人,hello实现是:“同学好”;学生的work实现是:认真学习,hello实现是“老师好”。

package com.atguigu.exer8;

public abstract class Person {
    String name;
    String sex;
    int age;

    public Person(){

    }

    public Person(String name,String sex,int age){
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public abstract void showInfo();
    public abstract void work();
    public abstract void hello();
}

package com.atguigu.exer8;

public class Teacher extends Person{

    public Teacher(String name,String sex,int age){
        super(name,sex,age);
    }

    @Override
    public void work() {
        System.out.println("教书育人!");
    }

    @Override
    public void hello() {
        System.out.println("同学好!");
    }

    @Override
    public void showInfo() {
        System.out.println("Teacher[name = " + name + ",sex = " +
                sex + ",age = " + age);
    }
}

package com.atguigu.exer8;

public class Student extends Person{

    public Student(String name,String sex,int age){
        super(name,sex,age);
    }

    @Override
    public void work() {
        System.out.println("认真学习!");
    }

    @Override
    public void hello() {
        System.out.println("老师好!");
    }

    @Override
    public void showInfo() {
        System.out.println("Student[name = " + name + ",sex = " +
                sex + ",age = " + age);
    }
}

static的使用

是否可以从一个static方法内部发出对非static方法的调用?

答:不可以,如果其中包含对象的method();不能保证对象初始化.

编译是否通过?

public class Something {
     public static void main(String[] args) {
        Something s = new Something();
        System.out.println("s.doSomething() returns " + doSomething());
    }
    public String doSomething() {
        return "Do something ...";
    }
}

答案: 错。main是static的。static method不能直接call non-static methods。
可改成"System.out.println(“s.doSomething() returns " + s.doSomething());”。
同理,static method不能访问non-static instant variable。

写出程序结果

public class Demo {
	private static int j = 0;

	private static boolean methodB(int k) {
		j += k;
		return true;
	}

	public static void methodA(int i) {
		boolean b;
		b = i < 10 | methodB(4);
		b = i < 10 || methodB(8);
	}

	public static void main(String args[]) {
		methodA(0);
		System.out.println(j);
	}
}

4 注意 逻辑或 和 短路或

final关键字

谈谈final, finally, finalize的区别(后面异常中讲finally)

答:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载

finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)

finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的

如下程序是否可通过编译?

public class Something {
   public int addOne(final int x) {
       return ++x;
   }
}

答案: 错。int x被修饰成final,意味着x不能在addOne method中被修改

public class Something {
   public static void main(String[] args) {
       Other o = new Other();
       new Something().addOne(o);
   }
   public void addOne(final Other o) {
       o.i++;
   }
}
class Other {
   public int i;
}

答案: 正确。在addOne method中,参数o被修饰成final。如果在addOne method里我们修改了o的reference
(比如: o = new Other(),那么如同上例这题也是错的。但这里修改的是o的member vairable(成员变量),而o的reference并没有改变。

class Something {
    int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
} 

答案: 正确。输出的是"i = 0"。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。int的default value是0。

//接上题
class Something {
    final int i;
    public void doSomething() {
        System.out.println("i = " + i);
    }
}

和上面一题只有一个地方不同,就是多了一个final。这难道就错了吗?
答案: 错。final int i是个final的instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为"final int i = 0;"。

代码块

以下代码的运行结果是?

public class Test {
	static int x, y, z;

	static {
		int x = 5;
		x--;
	}

	static {
		x--;
	}

	public static void main(String[] args) {
		System.out.println("x=" + x);
		z--;
		method();
		System.out.println("result:" + (z + y + ++z));
	}

	public static void method() {
		y = z++ + ++z;
	}
}

x=-1
result:3
对属性赋值的先后顺序 完结版 : (从前往后)默认初始化 — 显示初始化 / 代码块赋值 ----- 构造器赋值 ---- 对象.属性 或者 对象.方法
对第二个静态构造器赋值时,x = 0,x-- ,所以 x = - 1

参考资料

尚硅谷-Java零基础教程

你可能感兴趣的:(#,JavaSE,java,面向对象编程,idea)