Java基础面试

1. 面向对象和面向过程的区别

面向过程
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
缺点:性能比面向过程低

2. Java的四个基本特性(抽象、封装、继承,多态)

抽象:就是把现实生活中的某一类东西提取出来,用程序代码表示,我们通常叫做类或者接口。抽象包括两个方面:一个是数据抽象,一个是过程抽象。数据抽象也就是对象的属性。过程抽象是对象的行为特征。
封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行封装隐藏。封装分为属性的封装和方法的封装。
继承:是对有着共同特性的多类事物,进行再抽象成一个类。这个类就是多类事物的父类。父类的意义在于抽取多类事物的共性。
多态:允许不同类的对象对同一消息做出响应。方法的重载、类的覆盖正体现了多态。

3. 重载和重写的区别

重载:发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。
重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型/顺序。重载是一个类中多态性的一种表现。

重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。
父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。

4. String和StringBuffer、StringBuilder的区别

可变性:
String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。对String对象各种操作都不会改变其内部的字符数组,而是返回一个新的字符串对象。
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。
线程安全性:
String中的对象是不可变的,也就可以理解为常量,线程安全。
AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
性能:
每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。StringBuffer每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

5. 抽象类和接口的区别

语法层次:
抽象类和接口分别给出了不同的语法定义
设计层次:
抽象层次不同,抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
跨域不同:
抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a” 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已,”like-a”的关系。 即当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。

1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。因为抽象类可以有自己的成员变量,所以抽象类有构造函数,当实例化子类对象时会为抽象类成员变量初始化。

2、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现。

3、接口里定义的变量只能是公共的静态的常量(public static final),抽象类中的变量是普通变量(成员属性)。

4、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

5、抽象方法只有声明,不能实现。abstract void abc();不能写成abstract void abc(){}。

6、抽象类里可以没有抽象方法。

7、如果一个类里有抽象方法,那么这个类只能是抽象类。

8、抽象方法要被实现,所以不能是静态的,也不能是私有的。

9、接口可继承接口,并可多继承接口,但类只能单根继承。

关于访问修饰符:
对于抽象类和接口本身,它们的默认修饰符就是public!
一、接口中可用的修饰符(可省略)
1、在成员变量中,默认就是public final static,且必须显示初始化(接口中static块);
2、在方法(抽象方法)中,默认就是public abstract。
注解:接口是一种标准,是实现Java多态的一种重要机制,使用接口意味着对外暴露内部的标准,别人通过实现接口来实现它的标准,所以在接口中自然不能用protected和private这些有保护性质的修饰符。

二、抽象类中的修饰符
1、抽象类中的抽象方法(其前有abstract修饰)不能用private、final、static、synchronized、native访问修饰符修饰。原因如下:抽象方法没有方法体,是用来被继承的,所以不能用private修饰;static修饰的方法可以通过类名来访问该方法(即该方法的方法体),抽象方法用static修饰没有意义;使用synchronized关键字是为该方法加一个锁。。而如果该关键字修饰的方法是static方法。则使用的锁就是class变量的锁。如果是修饰类方法。则用this变量锁。但是抽象类不能实例化对象,因为该方法不是在该抽象类中实现的。是在其子类实现的。所以。锁应该归其子类所有。所以。抽象方法也就不能用synchronized关键字修饰了;native,这个东西本身就和abstract冲突,他们都是方法的声明,只是一个吧方法实现移交给子类,另一个是移交给本地操作系统。如果同时出现,就相当于即把实现移交给子类,又把实现移交给本地操作系统,那到底谁来实现具体方法呢?
对于抽象类中的抽象方法,访问修饰符可以是:默认、protected、public。
2、成员变量和普通类一样。

6. 内部类

http://blog.csdn.net/justloveyou_/article/details/53245561
Java 提供了两种方式让我们曲折地来实现多重继承:接口和内部类。事实上,实现多重继承是内部类的一个极其重要的应用。除此之外,内部类还可以很好的实现隐藏(例如,私有成员内部类)。
内部类是一个编译时的概念,一旦编译成功,内部类和外部类就会成为两个完全不同的类。因此,内部类的成员变量/方法名可以和外部类的相同。

分类:

  • 成员内部类:成员内部类是外围类的一个成员,是依附于外围类的,所以,只有先创建了外围类对象才能够创建内部类对象。也正是由于这个原因,成员内部类也不能含有 static 的变量和方法; 可以包含 static final 域,但该域的初始化必须是一个常量表达式;内部类可以继承含有static成员的类。
  • 静态内部类:静态内部类,就是修饰为 static 的内部类,该内部类对象 不依赖于外部类对象,就是说我们可以直接创建内部类对象,但其只可以直接访问外部类的所有静态成员和静态方法;
  • 局部内部类:局部内部类和成员内部类一样被编译,只是它的 作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效;
  • 匿名内部类:定义匿名内部类的前提是,内部类必须要继承一个类或者实现接口,格式为 new 父类或者接口(){定义子类的内容(如函数等)}。也就是说,匿名内部类最终提供给我们的是一个匿名子类的对象。

作用:

  • 内部类可以很好的实现隐藏(一般的非内部类,是不允许有 private 与 protected 权限的,但内部类可以);
  • 内部类拥有外围类的所有元素的访问权限;
  • 可以实现多重继承;
  • 可以避免修改接口而实现同一个类中两种同名方法的调用。通过使用内部类来实现接口,就不会与外围类所继承的同名方法冲突了。

7. 动态绑定

重载是编译时绑定,重写是运行时绑定。

例如:方法参数是一个接口类型,在程序运行期间,虚拟机会根据传入的具体的对象,来调用某一个类方法。

针对一个方法的调用:x.f(param),编译器只会检查x所声明的类及其父类:
这里写图片描述

至此,编译器已经获得需要调用的方法名字和参数类型。

对于运行时绑定,检查x实际引用的那个对象的类及其父类:是否有方法的重写
这里写图片描述

8. 枚举类

interface Run {
    public static final int a = 1;

    void run();
}

enum Size implements Run
{
    SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");

    private Size(String abbreviation) { this.abbreviation = abbreviation; }

    public String getAbbreviation() { return abbreviation; }

    private String abbreviation;

    public void run() {
        System.out.println("Size run");
    }

    public static void main(String[] args) {
        System.out.println(Size.SMALL);
    }
}

枚举类型是那些字段由一组固定常量组成的类型。常见的例子有:东南西北四个方向,星期几等。
所有枚举类型都隐式继承Java.lang.Enum类型,因为java不支持多重继承,所以枚举不能继承其他任何类。
java对枚举的支持是语言级的支持,switch-case结构无需加枚举名作为前缀。
多个枚举常量之间以逗号隔开,枚举常量列表最后可以以分号结束,如果有成员方法或成员变量,必须以分号结束。
枚举类型可以有成员方法和成员变量。如果有成员方法和成员变量,枚举常量列表要放在枚举体最开始,以分号结尾。
枚举类型的构造器必须是包级私有或者私有,构造器会自动创建枚举类型体开端定义的枚举常量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值