Java面试题-day03面向对象

面向对象

1) 你对面向对象思想的理解?

面向对象编程(Object-Oriented Programming)简称OOP技术,是开发计算机应用程序的一种新方法、新思想。过去的面向过程编程中常常会导致所有的代码都包含在几个模块中,使程序难以阅读和维护,在做一些修改时常常牵一动百,使以后的开发和维护难以为继。而使用OOP技术,使用许多代码模块,每个模块都只提供特定的功能,它们是彼此独立的,可以增加代码重用的几率,更加有利于软件的开发、维护和升级。另外OOP的三大核心特性:继承、封装、多态的特性,使得在面对象编上能够设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低,所以这一编程思想是目前一种应用最为普遍的软件设计思想。

封装
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。

继承
在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

多态
多态指的同一个对象,在程序不同时刻的多种运行状态。举例:水(气态,液态,固态)。
所谓多态,指的就是父类引用指向子类对象,调用方法时会调用子类的实现而不是父类的实现。多态的实现的关键在于“动态绑定”。

为使多态能运行,存在着继承或者实现关系
可以将子类的对象赋给父类/接口,以多态的形式来传递参数,增强了参数类型的灵活性。即父类(接口)引用指向子类(实现)对象

多态的好处和弊端:
好处:多态的存在提高了程序的扩展性和后期可维护性
弊端:虽然可以预先使用,但是只能访问父类中已有的功能,运行的是后期子类的功能内容。不能预先使用子类中定义的特有功能。

多态应用场景:当接口已经确定,但同一个接口在不同环境需要不同实现的时候。如:工厂模式
工厂方法模式(Factory Mehtod Pattern):定义一个用于创建对象的接口,让子类决定哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又称为工厂模式,又称为虚拟构造器模式或多态工厂模式。工厂方法模式是一种类创建型模式。

2) object中定义了哪些方法?

protected Object clone() 创建并返回此对象的一个副本。

boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。

protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

Class<?> getClass() 返回此 Object 的运行时类。

int hashCode() 返回该对象的哈希码值。

void notify() 唤醒在此对象监视器上等待的单个线程。

void notifyAll() 唤醒在此对象监视器上等待的所有线程。

String toString() 返回该对象的字符串表示。

void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。

void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。

void wait(long timeout, int nanos) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

3) Java对象初始化顺序

分为两种,一种是本类的初始化,一种是含有父类的初始化顺序。
本类的初始化顺序是:静态变量、静态初始化块、变量、初始化块、构造函数
继承类的初始化顺序是:父类静态变量、父类静态初始化块、子类静态变量、子类静态初始块、父类变量、父类初始化块、父类构造函数、子类变量、子类初始化块、子类构造函数。

【分析】
static{
System.out.println(“静态块”);
}
{
System.out.println(“初始化模块”); }
public ClassName() {
System.out.println(“构造方法”);
}

说明:
原则上回答全面的话,应该是完整的说出带有继承的这种类的初始化过程,下面有个步骤可以参考:

1.装载程序的时候首先找到的是它的基(父)类,如果有多层基(父)类则会一级一级的往上找最后找到根基(父)类。
2.执行根基础(父)类中的static初始化,再执行下一个衍生类中的static,依此类推,一直保持这个顺序。
3.此时类已经装载完毕,开始创建对象,所有的基本数据类型都会设成它们的默认值,对象句柄设为null
4.调用基础(父)类的构造方法,基础(父)类的构建采用与衍生类构造方法完全相同的处理过程。
5.构造方法初始完之后,进行变量的初始化。
6.执行构造方法中剩余的部分。

4) 方法的覆盖/重写Overload和Override的区别?Overload的方法是否 可以改变返回值的类型?

Overload是重载,Override是覆盖,也就是重写。
重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。

重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。是否可以改变返回值类型,在重载的定义中,与方法是什么类型返回值无关

5) abstract class(抽象类)和interface(接口)有什么区别?

含有abstract修饰符的class即为抽象类,abstract类不能创建实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义(抽象方法),而没有变量和方法的实现。

抽象类:有抽象方法和非抽象方法

接口:所有方法都是抽象的

一个接口可以实现多个父接口,将实现的各个接口用,隔开。

接口的特点
A:是对外暴露的规则
B:是功能的扩展
C:接口的出现降低耦合性。
耦合(类与类之间的关系)
内聚(类完成功能的能力)
编程规范:高内聚低耦合
D:接口可以多实现。如:CPU和主板、笔记本的USB插口、插座

6) abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

abstract的method不可以是static的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系!

native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。

synchronized和abstract合用的问题不能共用,abstract方法只能存在于抽象类或接口中,它不能直接产生对象,而默认synchronized方法对当前对象加锁,没有对象是不能加锁。

另外synchronized不能被继承,子类继承时,需要另加修改符。

7) static关键字

静态初始化块:static{ } : 使用static来修饰的自由块只在类加载的时候执行一次,通常用于初始化静态变量。

    A:它只执行一次,它比main还先执行。
	B:执行顺序是静态代码块--构造方法

static关键字声明属性(类属性):可以被该类的所有实例对象所共享
static关键字声明方法:可以在不创建对象的情况下,直接使用类名.方法名()的形式调用
静态方法只能访问静态成员

static属性,方法消耗大,要慎用。
静态的特点:

     随着类的加载而加载
     优先于对象存在
     对所有对象共享
     可以被类名直接调用

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

不可以。

因为非static方法(实例方法)是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

9) 静态变量和成员/实例变量的区别

A:调用方式
静态变量也称为类变量,可以直接通过类名调用。也可以通过对象名调用。这个变量属于类。
成员变量也称为实例变量,只能通过对象名调用。这个变量属于对象。

B:存储位置
静态变量存储在方法区栈中的静态区。
成员变量存储在堆内存。

C:生命周期
静态变量随着类的加载而存在,随着类的消失而消失。生命周期长。
成员变量随着对象的创建而存在,随着对象的消失而消失。

D:与对象的相关性
静态变量是所有对象共享的数据。
成员变量是每个对象所特有的数据。
静态方法可以调用其它的静态方法,但是不能调用非静态方法,这个好比Java中的类变量与实例变量的关系。类变量是被所有类成员共享,而实例变量只被该实例共享

10) 单态(Singleton)设计模式在实际开发中常用到,比如数据库的链接。使用Singleton模式可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收。

单态设计模式创建一个类,应满足:

*为了避免其他程序建立该类对象,先禁止其他程序建立该类对象,即将构造函数私有化
*为了其他程序访问到该类对象,须在本类中创建一个该类私有对象
*为了方便其他程序访问到该类对象,可对外提供一个公共访问方式

Runtime类就是单例设计模式。
单例设计模式的两种方式
A:饿汉式当类加载的时候,就创建对象。


class Single
		{
    
    
			private Single(){
    
    }//将构造函数私有化,不让别的类建立该类对象
			private static final Single s=new Single();//自己建立一个对象
			public static Single getInstance()//提供一个公共访问方式
			{
    
    
				return s;
			}
		}	



B:懒汉式当使用的使用,才去创建对象。

class Single{
    
    
			private Single(){
    
    } 
			private static Single s;
			public static Single getInstance(){
    
    
				if(s==null)
					s=new Single();
				return s;
			}



饿汉式和懒汉式的区别:

	饿汉式是类一加载进内存就创建好了对象;
	懒汉式则是类才加载进内存的时候,对象还没有存在,只有调用了				
	getInstance()方法时,
	对象才开始创建。
	**
	懒汉式是延迟加载,如果多个线程同时操作懒汉式时就有可能出现线			
	程安全问题,解决线程安全问题
		可以加同步来解决。但是加了同步之后,每一次都要比较锁,效率就		
			变慢了,所以可以加双重判断来提高程序效率。

如将上述懒汉式的Instance函数改成同步:

public static Single getInstance(){
    
    
			if(s==null){
    
    
				synchronized(Single.class)
				{
    
    
					if(s==null) 
						s=new Single();
				}
			}
			return s;
		}
注:开发常用饿汉式,因为饿汉式简单安全。懒汉式多线程的时候易发生问题

11) final关键字

final类:不可被继承,如java.lang.Math就是一个final类,不可被继承。

final变量:在初始化后不可改变变量值,用于常量定义。如果final变量是引用变量,则不可以改变它的引用对象,但可以改变对象的属性。final修饰的变量是一个常量。只能被赋值一次
final方法:不可被重写

定义常量:
//static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。
public static final double pi=3.14;

12) 内部类

定义在一个类内部的类(inner class)
内部类的对象能访问它所处类的私有数据
内部类能隐藏起来不为同一个包中其他类访问
当内部类定义在外部类的成员位置,而且非私有,则可以在其他外部类中直接建立内部类对象
格式:外部类名.内部类名变量名 = new 外部类对象.内部类对象
如:Outer.Inner in = new Outer().new Inner()

13) 匿名内部类

	(1)前提:继承一个类或者实现一个接口

	(2)格式:
		new 父类名或者接口名()
		{
			重写父类方法或者实现接口中的方法。
			也可以自定义其他方法。
		};
	(3)什么时候定义匿名内部类?
		匿名内部类只是为了简化书写,匿名内部类有局限,通常定义匿				名内部类时,该类方法不超过3个
	(4)匿名内部类的好处和弊端:
		好处:简化代码书写
		弊端:
			不能直接调用自己的特有方法
			不能执行强转换动作
		如果该类里面方法较多,不允许使用匿名内部类

14) String是最基本的数据类型吗?

基本数据类型包括byte、int、char、long、float、double、boolean和short。
String是引用数据类型。

java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer/StringBuilder类

15) String类方法(不可改变)

Java 中的 String 不可变是因为 Java 的设计者认为字符串使用非常频繁,将字符串设置为不可变可以允许多个客户端之间共享相同的字符串。

java中字符串的处理专门有String类提供的很多API可以很方便的对字符串进行各种操作,如截取、查询、转换成其它类型。特别是在结合正则表达式可以灵活的对字符串进行筛选。

		获取方法
		int length()  获取字符串的长度
		charcharAt(intindex)获取特定位置的字符(角标越界)
		int indexOf(String str) 获取特定字符的位置(overload)
		
		intlastIndexOf(intch)获取最后一个字符的位置
		判断方法
		boolean endsWith(String str) 是否以指定字符结束
		booleanisEmpty()是否长度为0如:“”nullV1.6
		booleancontains(CharSequences)是否包含指定序列应用:搜索
		booleanequals(ObjectanObject)是否相等

		 booleanequalsIgnoreCase(StringanotherString)忽略大小写是否相等
		转换方法
		String(char[]value)将字符数组转换为字符串
		String(char[]value,intoffset,intcount)
		StaticStringvalueOf(char[]data)
		staticStringvalueOf(char[]data,intoffset,intcount)
		char[]toCharArray()将字符串转换为字符数组
		转换方法
		Stringreplace(charoldChar,charnewChar)替换
		
		String[]split(Stringregex)切割
		Stringsubstring(intbeginIndex)
		Stringsubstring(intbeginIndex,intendIndex)截取字串
		String toUpperCase()转大写
		StringtoLowerCase()转小写

16) StringBuffer与StringBuilder的区别

这两个类都实现了CharSequence接口。

  1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用
  2. String对象是不可变对象,不能修改值。StringBuffer是可变对象,能修改值。
  3. 拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。
  4. String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。

17) 用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

引用变量不能重新赋值,但是引用指向的对象的内容可以变化

例1:final StringBuffer a=new StringBuffer(“immutable”);
a=new StringBuffer("");
有编译错

例2:
final StringBuffer a=new StringBuffer(“immutable”);
a.append(“123”);
正确

猜你喜欢

转载自blog.csdn.net/m0_56368068/article/details/120688440