java程序员面试笔试宝典-4.2面向对象技术

参考 java_1101
liu0yun

4.2.1面向过程与面向对象的比较

面向过程:

一种较早的编程思想,顾名思义就是该思想是站着过程的角度思考问题,强调的就是功能行为,功能的执行过程,即先后顺序,而每一个功能我们都使用函数(类似于方法)把这些步骤一步一步实现。使用的时候依次调用函数就可以了。

面向过程的设计:

最小的程序单元是函数,每个函数负责完成某一个功能,用于接受输入数据,函数对输入数据进行处理,然后输出结果数据,整个软件系统由一个个的函数组成,其中作为程序入口的函数称之为主函数,主函数依次调用其他函数,普通函数之间可以相互调用,从而实现整个系统功能。
  面向过程最大的问题在于随着系统的膨胀,面向过程将无法应付,最终导致系统的崩溃。为了解决这一种软件危机,我们提出面向对象思想。

面向过程的缺陷:

是采用指定而下的设计模式,在设计阶段就需要考虑每一个模块应该分解成哪些子模块,每一个子模块又细分为更小的子模块,如此类推,直到将模块细化为一个个函数。

存在的问题

设计不够直观,与人类的思维习惯不一致
系统软件适应新差,可拓展性差,维护性低

面向对象:

一种基于面向过程的新编程思想,顾名思义就是该思想是站在对象的角度思考问题,我们把多个功能合理放到不同对象里,强调的是具备某些功能的对象。
  具备某种功能的实体,称为对象。面向对象最小的程序单元是:类。面向对象更加符合常规的思维方式,稳定性好,可重用性强,易于开发大型软件产品,有良好的可维护性。
  在软件工程上,面向对象可以使工程更加模块化,实现更低的耦合和更高的内聚。

面向对象和面向过程有什么区别

面向过程是围绕功能进行的,为每一个功能写一个函数,需要考虑其中的每一个细节,以步骤划分,可以这么比喻

                                面向过程的程序=算法+数据结构

而面向对象则像是组装,先确定一个系统是由哪些对象组成,再分别去设计这些对象,将它们像零件一样组装起来形成有完整功能的系统,以功能划分,相当于

                             对象=算法+数据结构

                          面向对象的程序=N个对象+控制信息

面向对象和面向过程的区别 就像是面向过程程序只用函数实现,而面向对象程序是用类实现各个功能模块。

有人这么比喻:

“如五子棋,面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。

如果是面向对象的设计思想来解决问题。面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。”

注意:千万不要误解为面向对象一定就优于面向过程的设计。

4.2.2 面向对象特征有哪些?

抽象、继承、封装和多态。

抽象:分过程抽象和数据抽象。忽略与当前目标无关的方面,充分注意与当前目标有关方面。
继承:连结类的层次模式-鼓励类重用,提供明确表示共性方法。继承:连结类的层次模式-鼓励类重用,提供明确表示共性方法。
封装:将客观事物抽象为类,由类自身对数据和方法进行保护与操作,对不可信信息隐藏。封装:将客观事物抽象为类,由类自身对数据和方法进行保护与操作,对不可信信息隐藏。
多态:允许不同类对象对同一信息做响应。参数化多态和包含多态。多态:允许不同类对象对同一信息做响应。参数化多态和包含多态。

4.2.3 面向对象软件开发的优点有哪些?

代码开发模块化,更易维护和修改。
代码复用。
增强代码的可靠性和灵活性。
增加代码的可理解性。
面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象。

4.2.4 继承主要有如下几个特征

1)不支持多重继承
2)子类只能继承父类非私有(public,protected)成员变量和方法
3)当子类的成员变量和父类的成员变量同名时,子类中的成员变量会覆盖父类中的成员变量,而不会继承。
4)当子类中的方法与父类中的方法有相同的函数签名时,子类会覆盖父类的方法而不会继承

函数签名-(相同的方法名、相同的参数个数与类型)

4.2.5组合和继承的区别

组合是指在新类里面创建原有类的对象;
组合和继承的区别:
例如:Car表示汽车对象,Vehicle表示交通工具,Tire表示轮胎对象
is-a关系用继承表示
has-a关系用组合表示

4.2.6多态实现的机制是什么?

多态表现:方法重载,方法覆盖。

重载指类中多个同名方法,方法参数不同,由编译时确定调用何种,是编译时多态。类中方法多态性。

覆盖,是子类覆盖父类。基类引用可指向基类实例或其子类实例。接口引用可指向实现其的实例对象。程序调用时运行期间动态绑定(引用变量所指向具体实例对象方法,而非引用类型的实例对象方法),运行时多态。

package cn.itcast;

public class Base {
	public Base(){
		g();
	}
	public void f(){
		System.out.println("Base f()");
	}
	public void g(){
		System.out.println("Base g()");
	}
}

package cn.itcast;

public class Derived extends Base {
	public void f(){
		System.out.println("Derived f()");
	}
	public void g(){
		System.out.println("Derived g()");
	}
}

package cn.itcast;

public class Test {

	public static void main(String[] args) {
		Base b = new Derived();
		b.f();
		b.g();
	}

}

在这里插入图片描述
此外,只有类中的方法才有多态的概念,类中成员变量是没有多态的概念的

package cn.itcast1;

public class Base {
	public int i = 1;
}

package cn.itcast1;

public class Derived extends Base {
	public int i = 2;
}

package cn.itcast1;

public class Test {

	public static void main(String[] args) {
		Base b = new Derived();
		System.out.println(b.i);
		Base b1 = new Base();
		System.out.println(b1.i);
		Derived b2 = new Derived();
		System.out.println(b2.i);
	}

}

在这里插入图片描述
  运行时多态是对于方法而非成员变量。成员变量值取父类还是子类取决于定义变量类型,编译期间确定。

4.2.7重载和覆盖的区别 ?

在使用重载的时候需要注意:

1)重载是通过不同的方法参数来区分的
2)不能通过方法的访问权限,返回值类型和抛出的异常类型进行重载
3)对于继承来说,如果基类方法是private,就不能在派生类中进行重载;如果派生类也定义了一个同名函数,则只是一个新的方法。

在使用覆盖时需要注意:

1)派生类中的覆盖方法必须与基类中被覆盖方法有相同的函数名和参数。
2)派生类中的覆盖方法的返回值必须与基类中被覆盖方法的返回值相同。
3)派生类中的覆盖方法所抛出的异常必须与基类中被覆盖的方法所抛出的异常一致。
4)基类中被覆盖的方法不能为private,否则其子类只是定义了一个方法。

重载和覆盖的区别:

1)覆盖是子类和父类的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。
2)覆盖只能由一个方法或只能由一对方法产生关系;重载是多个方法之间的关系。
3)覆盖要求参数列表相同,重载要求参数列表不同。
4)覆盖关系中,调用方法体是根据对象的类型来决定;而重载关系是根据调用时的实参表与形参表来选择方法体的。
在这里插入图片描述
编译错误:因为函数是不能以返回值来区分的

4.2.8抽象类和接口的异同

相同点:

1)都不能被实例化
2)接口的实现类或抽象类的子类都只有在实现了接口或抽象类中的方法之后才可以被实例化。

不同点:

1)接口只有定义,没有实现
2)接口需要实现(implements),抽象类需要继承(extends)
3)接口强调has-a,抽象类强调is-a
4)接口中的成员变量默认是:public static final,而且必须赋初值;成员方法都是public abstract
5)接口用于实现常用功能,抽象类用于充当公共类的角色。

4.2.9内部类有哪些?(静态内部类;成员内部类;局部内部类;匿名内部类)

package com.zcl.test;

import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

class outerClass{
    static class innerClass{}//静态内部类
}

class outerClass1{
    class innerClass{};//成员内部类
}

class outerClass2{
    public void menberFunction(){
        class innerClass{}//局部内部类
    }
}

public class MyFrame extends Frame{
    public MyFrame(){
        addWindowListener(new WindowAdapter() {//匿名内部类
            public void windowClosing(WindowEvent e){
                dispose();
                System.exit(0);
            }
        });
    }
}

内部类分为4种

1)静态内部类可以不依赖外部类实例而被实例化;不能与外部类有相同的名字,只能访问外部类中的静态成员和静态方法。
2)成员内部类可以自由引用外部类的属性和方法,不可以定义静态的属性和方法。
3)局部内部类:定义在代码块中的类,只能访问方法中被定义为final类型的局部变量。
4)匿名内部类是一种没有类名的内部类,不适用关键字class,extends,implements,没有构造函数,必须继承其他类或实现其他接口,一般用于GUI图形用户界面编程中实现事件处理等。

匿名内部类注意事项:

1)匿名内部类不能有构造函数
2)匿名内部类不能定义静态成员,方法和类
3)匿名内部类不能是public,protected,private,static
4)只能创建匿名内部类的一个实例
5)一个匿名内部类一定是在new的后面,这个匿名内部类必须继承一个父类或实现一个接口
6)匿名内部类为局部内部类。

4.2.10如何获取父类的类名?

java语言提供了获取类名的方法getClass().getName()

package cn.itcast2;

public class Test {
	public void test(){
		System.out.println(this.getClass().getName());
	}
	public static void main(String[] args) {
		new Test().test();
	}
}

在这里插入图片描述

通过调用父类的getClass().getName()方法可行吗?

package cn.itcast2;

class A{}
public class Test1 extends A{
	public void test(){
		System.out.println(super.getClass().getName());
	}
	public static void main(String[] args) {
		new Test1().test();
	}
}

在这里插入图片描述

原因:

java语言中任何类都继承自Object类,getClass方法在Object中被定义为final和native,子类不能覆盖。
并且getClass()含义是返回运行时类,程序实际运行的是Test而不是A
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package cn.itcast3;

class A{}
public class Test extends A{
	public void test(){
		System.out.println(this.getClass().getSuperclass().getName());
	}
	public static void main(String[] args) {
		new Test().test();
	}
}

在这里插入图片描述

4.2.11this和super有什么区别?

在java语言中,this用来指向当前实例对象,它的一个非常重要的作用是:区分对象的成员变量和方法的形参。
因为当方法的形参与成员变量的名字相同时,就会覆盖成员变量。

例1:
class People{
    String name;
    //正确的写法
    public People(String name){
        this.name = name;
    }

    //错误的写法
    public People(String name){
        name = name;
    }
}

super可以访问父类的方法或成员变量。当子类的方法或成员变量与父类有相同名字时也会覆盖父类的方法或成员变量。

package cn.itcast3;

public class Base {
	public void f() {
		System.out.println("Base:f()");
	}
}

package cn.itcast3;

public class Sub extends Base {
	public void f(){
		System.out.println("Sub:f()");
	}
	public void sub(){
		f();
	}
	public void basef(){
		super.f();
	}
}

package cn.itcast3;

public class Test1 {

	public static void main(String[] args) {
		Sub s = new Sub();
		s.sub();
		s.basef();
	}

}

在这里插入图片描述

当子类构造函数需要显示调用父类的构造函数时,super()必须为构造函数中的第一条语句。

super();
System.out.println(“Sub”);
在这里插入图片描述

package cn.itcast4;

public class Base {
	public Base(){
		System.out.println("Base");
	}
}

package cn.itcast4;

public class Sub extends Base {
	public Sub(){
		super();
		System.out.println("Sub");
	}
}

package cn.itcast4;

public class Test {

	public static void main(String[] args) {
		Base s = new Sub();
	}

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值