为了九月秋招,现在开始面试打卡——第一天

现在已经是六月份了,为了九月份可以去一个好的公司,甚至是阿里,字节这样的大厂,我要开始准备背面试题了,从今天开始,每天打卡一次。

Java面向对象有哪些特征

面向对象有三大特征,继承,封装,多态

  • 封装隐藏了内部的实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据,对外界是内部细节是隐藏的,暴露给外界的只有访问方法。
  • 继承从已经有的类派生出新的类新的类拥有已经有的类的数据属性和行为,并可扩展性的能力,并可以具有父类不具有的某些属性或者方法。
  • 多态指的是类和类的关系,两个类由继承关系,存在方法的重写,所以可以在调用父类引用对象指向子类对象,多态必备三个要素:继承,父类引用指向子类对象,继承。

封装,继承增加了代码的复用性,多态增加了代码的健壮性,灵活性。

ArrayList和LinkList有什么区别

ArrayList和LinkList都实现了List接口,有以下不同点

  • ArrayList底层是数组,查询的速度很快
  • LinkList底层是链表,删除,新增数据很快
  • LinkList比ArrayList更占内存,因为LinkList每一个结点储存了两个引用,一个指向元素,一个指向下一个元素

JDK1.8的新特性

一、接口的默认方法

Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可,这个特征又叫做扩展方法,示例如下:
代码如下:

interface Formula {
      double calculate(int a);
default double sqrt(int a) {
      return Math.sqrt(a); }}

Formula接口在拥有calculate方法之外同时还定义了sqrt方法,实现了Formula接口的子类只需要实现一个calculate方法,默认方法sqrt将在子类上可以直接使用。
代码如下:

Formula formula = new Formula() {
      @Override public double calculate(int a) {
      return sqrt(a * 100);} };formula.calculate(100); l/ 100.0 formula.sqrt(16);ll4.0

文中的formula被实现为一个匿名类的实例,该代码非常容易理解,6行代码实现了计算sqrt(a * 100)。在下一节中,我们将会看到实现单方法接口的更简单的做法。
译者注:在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,在C++中支持多继承,允许一个子类同时具有多个父类的接口与功能,在其他语言中,让一个类同时具有其他的可复用代码的方法叫做mixin。新的Java 8的这个特新在编译器实现的角度上来说更加接近Scala的trait。在C#中也有名为扩展方法的概念,允许给已存在的类型扩展方法,和ava 8的这个在语义上有差别。

二、Lambda表达式

首先看看在老版本的Java中是如何排列字符串的:代码如下:

List<string> names = Arrays.asList("peterF", "anna", "mike" , "xenia");
Collections.sort(names, new Comparator<string>() {
      @Override public int compare(String a, String b){
     return b.compareTo(a); }});

只需要给静态方法Collections.sort传入一个List对象以及一个比较器来按指定顺序排列。通常做法都是创建一个匿名的比较器对象然后将其传递给sort方法。
在Java 8中你就没必要使用这种传统的匿名对象的方式了,Java 8提供了更简洁的语法,lambda表达式:代码如下:

Collections.sort(names, (String a, String b)-> {
      return b.compareTo(a); });

看到了吧,代码变得更段且更具有可读性,但是实际上还可以写得更短:代码如下:

Collections.sort(names, (String a, String b) -> b.compareTo(a));

对于函数体只有一行代码的,你可以去掉大括号以及return关键字,但是你还可以写得更短点:代码如下:

Collections.sort(names, (a, b) -> b.compareTo(a));

Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。接下来我们看看lambda表达式还能作出什么更方便的东西来:

三、函数式接口

Lambda表达式是如何在java的类型系统中表示的呢?每一个lambda表达式都对应一个类型,通常是接口类型。而"函数式接口"是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。因为默认方法不算抽象方法,所以你也可以给你的函数式接口添加默认方法。
我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型,确保你的接口一定达到这个要求,你只需要给你的接口添加@Functionallnterface注解,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的。
示例如下:代码如下:

@Functionalnterface interface Converter<F,T> {
     T convert(F from); } Converter<String, Integer> converter =(from) -> Integer.valueOf(from); Integer converted = converter.convert("123");
System.out.printIn(converted);ll 123

需要注意如果@Functionallnterface如果没有指定,上面的代码也是对的。
译者注将lambda表达式映射到一个单方法的接口上,这种做法在Java 8之前就有别的语言实现,比如RhinoJavaScript解释器,如果一个函数参数接收一个单方法的接口而你传递的是一个function,Rhino解释器会自动做一个单接口的实例到function的适配器,典型的应用场景有org.w3c.dom.events.EventTarget的
addEventListener第二个参数EventListener。

四、方法与构造函数引用

前一节中的代码还可以通过静态方法引用来表示:代码如下:

Converter<String, Integer> converter = Integer:valueOf; Integer converted = converter.convert("123");System.out.printIn(converted); l1 123

Java 8允许你使用:关键字来传递方法或者构造函数引用,上面的代码展示了如何引用一个静态方法,我们也可以引用一个对象的方法:
代码如下:

converter = somethingstartsWith; String converted = converter.convert("Java");System.out.println(converted); l/ "J"

接下来看看构造函数是如何使用:关键字来引用的,首先我们定义一个包含多个构造函数的简单类:代码如下:

class Person {
      String firstName; String lastName;Person()0
Person(String firstName, String lastName) {
      this.firstName = firstName; this.lastName = lastName;}}

接下来我们指定一个用来创建Person对象的对象工厂接口:
代码如下:

interface PersonFactory<P extends Person> {
      P create(String firstName, String lastName); }

这里我们使用构造函数引用来将他们关联起来,而不是实现一个完整的工厂:
代码如下:

PersonFactory<Person> personFactory = Person:new; Person person = personFactory.create(""Peter","Parker");

我们只需要使用Person:new来获取Person类构造函数的引用,Java编译器会自动根据PersonFactory.create方法的签名来选择合适的构造函数。

五、Lambda 作用域

在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
六、访问局部变量
我们可以直接在lambda表达式中访问外层的局部变量:代码如下:

final int num = 1; Converter<Integer, String> stringConverter =(from) -> String.valueOf(from + num);stringConverter.convert(2); 1/ 3

但是和匿名对象不同的是,这里的变量num可以不用声明为final,该代码同样正确:代码如下:

int num = 1;Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);stringConverter.convert(2);1l 3

不过这里的num必须不可被后面的代码修改(即隐性的具有final的语义),例如下面的就无法编译:代码如下:

int num = 1;Converter<Integer, String stringConverter = (from)-> String.valueOf(from + num); num = 3;

在lambda表达式中试图修改num同样是不允许的。

七、访问对象字段与静态变量

和本地变量不同的是,lambda内部对于实例的字段以及静态变量是即可读又可写。该行为和匿名对象是一致的:代码如下:

class Lambda4 {
      static int outerStaticNum; int outerNum;
void testScopes() {
      Converter<Integer, String> stringConverter1 = (from)-> {
      outerNum = 23; returnString.valueOf(from); };
Converter<Integer, String> stringConverter2 =(from) -> {
      outerStaticNum = 72; returnstring.valueOf(from); 3; }}

JAVA接口和抽象类有什么区别

相同:

  • 不能够实例化
  • 可以将抽象类和接口类型作为引用类型
  • 一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类

不同:抽象类:

  • 抽象类中可以定义构造器
  • 可以有抽象方法和具体方法
  • 接口中的成员全都是public的
  • 抽象类中可以定义成员变量
  • 有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法
  • 抽象类中可以包含静态方法
  • 一个类只能继承一个抽象类

不同:接口:

  • 接口中不能定义构造器
  • 方法全部都是抽象方法
  • 抽象类中的成员可以是private、默认、protected、public
  • 接口中定义的成员变量实际上都是常量
  • 接口中不能有静态方法
  • 一个类可以实现多个接口

什么时候用接口,时候用抽象

抽象和接口的语义是不一样的,抽象描述的是一种抽象概念,比方说“动物”,“植物”,“玩具”,而接口描述的是一类事物的共同特征比方说“会飞的”,“会跑的”,“长得帅的”,“长得美帝的”等等打个比方,迪迦可以有一个叫做“奥特曼”的抽象类,一个“会飞的”接口。

hashcode,equals如何使用

JDK1.8HashMap底层实现原理

Java中equals和==的区别

equals和==最大的区别是一个是方法一个是运算符。

  • ==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等。
  • equals():用来比较方法两个对象的内容是否相等。

注意: equals方法不能用于基本数据类型的变量,如果没有对 equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址。

Java异常处理机制是什么

为了九月秋招,现在开始面试打卡——第一天_第1张图片
Java通过面向对象的方法进行异常处理,一旦方法抛出异常,系统自动根据该异常对象寻找合适异常处理器(Exception Handler)来处理该异常,把各种不同的异常进行分类,并提供了良好的接口。
在Java中,每个异常都是一个对象,它是Throwable类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并可以对其进行处理。Java的异常处理是通过5个关键词来实现的: try、catch、throw、throws和finally。
在Java应用中,异常的处理机制分为声明异常,抛出异常和捕获异常。

throw和throws的区别:

位置不同:
throw:方法内部
throws:方法的签名处,方法的声明处
内容不同:
throw+异常对象(检查异常,运行时异常)throws+异常的类型(可以多个类型,用,拼接)
作用不同:
throw:异常出现的源头,制造异常。
throws:在方法的声明处,告诉方法的调用者,这个方法中可能会出现我声明的这些异常。然后调用者对这个异常进行处理:要么自己处理要么再继续向外抛出异常

你可能感兴趣的:(java,多态,抽象类,面试)