剑指offer(一)之Java基础

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013234928/article/details/89408403

JAVA 体系中分为几大类吧,每一类都值得好好研究一下。了解其原理,jdk 底层是如何实现的。一般面试的时候也会问到底层实现的原理,或者手写代码去实现。总之要想学好就要花心思了。

这里我将java 分为一下几类,和 话说面试 一样 作为一个入口,这里是Java体系入口。

Java

  1. Java–基础
  2. Java–集合类
  3. Java–多线程
  4. Java–网络通讯
  5. Java–IO
  6. Java–JDBC
  7. Java–JVM

文章就这么结束了,似乎太短了,那 Java–基础 就在这介绍了


Java–基础

1、标识符

标识符组成:

  • 使用字母、下划线(_)、美元符($)、人民币符号(¥) 和数字(不能以数字开头)
  • 大小写敏感,长度不限,不能使用关键字

命名约定:

  • 类和接口名:每个字的首字母大写,含有大小写,例如:MyClass
  • 方法名:首字符小写,其余的首字母大写,含大小写。尽量少用下划线,采用驼峰式命名,例如:myName
  • 常量名:常量名使用全部大写字母,字与字之间用下划线分隔,例如:SIZE_NAME
  • 变量名:可大小写混写,首字母小写,字间分隔符用字的首字母大写。不用下划线,少用美元符号。给变量命名是尽量做到见名知义。

2、基本数据类型和其封装类

  1. 基本数据类型和引用类型
  2. String
  3. float和double 精度问题
  4. 数组

3、访问控制级别

本类、同包、子类、不同包

private < default < protected < public

私有的private :本类
默认的default:本类、同一包
受保护protected:本类、同一包、被继承
公共的public:本类、同一包、被继承、不同包


4、逻辑运算与位运算

  1. 位运算
  2. 逻辑运算
  3. 方法参数传递的问题
  4. try{}catch(){}finally{} 中 return 的问题

5、关键字–final

  • final类不能被继承,没有子类,final类中的方法默认是final的。
  • final方法不能被子类的方法覆盖,但可以被继承。
  • final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
  • final不能用于修饰构造方法。

6、关键字–static

  • static:修饰的方法或变量,可以通过类名直接访问
  • static:可以用来修饰类的成员变量、代码块、成员方法
    • static变量: 静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
    • static代码块: 在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
    • static方法: 静态方法中不能用this和super关键字(因为this代表对象,而静态在时,有可能没有对象),不能直接访问所属类的实例变量和实例方法,只能访问所属类的静态成员变量和成员方法。

静态变量、成员变量、局部变量的区别

  • 静态变量可以被对象调用,也可以被类名调用。以static关键字申明的变量,其独立在对象之外,有许多对象共享的变量。在对象产生之前产生,存在于方法区静态区中。
  • 成员变量只能被对象调用。随着对象创建而存在,随对象销毁而销毁。存在于堆栈内存中
  • 局部变量在方法或语句块中申明的变量,生命周期只在定义的{}之中,不能跨方法或语句块使用。

所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据


7、抽象类和接口

  • 抽象类和接口都不能直接实例化;抽象方法必须由子类来进行重写
  • 抽象类单继承,接口多实现
  • 抽象类可有构造方法,普通成员变量,非抽象的普通方法,静态方法
  • 抽象类的抽象方法访问权限可以为:public、protected 、default
  • 接口中变量类型默认public staic final,接口中普通方法默认public abstract,没有具体实现
    jdk1.8 中接口可有静态方法和default(有方法体)方法

应用场合

  • 接口应用场景:
    • 需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。
  • 抽象类应用场景:
    • 在既需要统一的接口,又需要实例变量或缺省的方法的情况下就可以使用它
    • 定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口

8、方法重载和重写

Java的三大特性:封装、继承、多态。封装和继承目的都是为了代码重用,多态目的是为了接口重用。

  • 封装:是把客观事物抽象成类,并且把自己的属性和方法让可信的类或对象操作,对不可性的隐藏。
  • 继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
  • 多态:允许将子类类型的指针赋值给父类类型的指针。

多态性体现:方法重载、方法重写、抽象类、接口

重写0veriding和重载Overloading

  • 重写:发生在继承类中,方法名和参数列表相同,权限修饰符大于等于父类、返回值类型小于等于父类、抛出异常小于等于父类

  • 重载:发生在同一个类中,方法名相同,参数列表不同,与权限修饰、返回值类型、抛出异常无关


9、类加载

1> 类加载方式

  • 静态加载:编译时刻加载的类是静态加载类,new关键字来实例对象,编译时执行
  • 动态加载: 运行时刻加载的类是动态加载类,反射方式加载,运行期执行

2> 创建一个对象的几种方式

  • 使用new关键字
  • 使用反射
  • 使用clone方法
  • 使用序列化

3> 类初始化时机

  • 使用new 实例化对象时
  • 调用静态变量时(常量除外)、静态方法
  • 通过反射调用
  • 初始化一个类如果父类没有初始化,先触发父类的初始化
  • 执行main方法的启动类

注意:

  1. 子类调用父类的静态变量,子类不会被初始化。只有父类被初始化。对于静态字段,只有直接定义这个字段的类才会被初始化.
  2. 通过数组定义来引用类,不会触发类的初始化
  3. 访问类的常量,不会初始化类

初始化内容:

  • 一个类的静态属性、静态块、普通属性、普通方法块、构造函数

4> 类初始化顺序

代码演示详情

  • 先加载静态的属性和静态块,此二者谁定义在前,先初始化谁
  • 在加载普通属性、普通方法块,此二者谁定义在前,先初始化谁
  • 然后加载构造函数,构造函数调new 谁,加载谁
  • 最后调用普通方法

有继承的子类:

  • 先加载静态的属性和静态块,不过先加载父类的,然后子类
  • 再加载先加载父类的普通属性、普通方法块、构造函数
  • 再加载先加载子类的普通属性、普通方法块、构造函数

10、深拷贝和浅拷贝

浅拷贝: 对基本数据类型进行值拷贝,对引用数据类型的引用地址进行拷贝,此为浅拷贝。

深拷贝: 对基本数据类型进行值拷贝,对引用数据类型的内容进行拷贝,此为深拷贝。

浅拷贝:必须实现Cloneable接口,并覆写clone()方法

public class Body implements Cloneable{
    private Head head;
    private int age;
    public Body() {}
    public Body(Head head) {this.head = head;}
    @Override
    protected Object clone() throws CloneNotSupportedException {
       return super.clone();
    }
}

深拷贝:两种方式,序列化、Clonable接口

  • 序列化(serialization)这个对象,再反序列化回来,就可以得到这个新的对象,无非就是序列化的规则需要我们自己来写。
  • 实现Clonable接口,覆盖并重写clone(),除了调用父类中的clone方法得到新的对象, 还要将该类中的引用变量也clone出来。如果只是用Object中默认的clone方法,是浅拷贝的
public class Body implements Cloneable{
    private Head head;
    private int age;
    public Body() {}
    public Body(Head head) {this.head = head;}

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Body newBody =  (Body) super.clone();
        newBody.head = (Head) head.clone();
        return newBody;
    }
}

11、异常

Exception 和Error 都是继承了Throwable类

  • Exception:
    • 是程序本身可以预料、可以处理的异常,应该被捕获。
    • Exception又分为可检查(checked)异常和不可检查(unchecked)异常。
      • 可检查异常: Java编译器要求必须捕获或抛出
      • 不可检查时异常: Java编译器不要求一定捕获或抛出,可以不做处理。像NullPointerException、ArrayIndexOutOfBoundsException之类,
  • Error:
    • 是程序无法处理的错误,不便于也不需要捕获
    • 常见的比如OOM和SOF之类都是Error的子类。

12、反射

1> 反射机制概述

  • 反射就是通过字节码文件找到某一个类、类中的方法以及属性等
  • Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。

2> 反射的3种实现方式

  • 直接通过类名.class方式获得:Class clazz = User.class;
  • 通过对象的getClass()方法获取:User user =new User();Class<?> clazz =user.getClass();
  • 通过全类名获取:Class<?> clazz = Class.forName(“com.bobo.User”);

3> 反射常用类

Class:类的对象

Constructor:类的构造方法

Field:类中的属性对象

Method:类中的方法对象

4> 反射机制的优缺点

  • 优点:

    (1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
    (2)与Java动态编译相结合,可以实现无比强大的功能

  • 缺点:
    (1)使用反射的性能较低
    (2)使用反射相对来说不安全
    (3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性

5 > 反射中Class.forName()和ClassLoader.loadClass()的区别

  • Class.forName除了将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。
  • ClassLoader只将.class文件加载到jvm中,不会执行static块中的内容,只有在newInstance才会去执行static块。ClassLoader.loadClass().newInstance()
  • Class.forName(name,initialize,loader)通过参数控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象。

13、类的关系

这一块内容 有参考博文:https://blog.csdn.net/xingjiarong/article/details/50193815

在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)

  • 泛化:是一种继承关系;
    • 带三角箭头的实线,箭头指向父类
  • 实现:是一种类与接口的关系;
    • 带三角箭头的虚线,箭头指向接口
  • 关联:是一种拥有的关系,
    • 对象成员变量;
    • 带普通箭头的实心线,指向被拥有者
  • 聚合:是整体与部分的关系;且部分可以离开整体而单独存在;
    • 在代码实现聚合关系时,成员对象通常作为构造方法、Setter方法或业务方法的参数注入到整体对象中。
    • 带空心菱形的实心线,菱形指向整体
  • 组合:是整体与部分的关系,但部分不能离开整体而单独存在;如公司和部门是整体和部分的关系,没有公司就不存在部门。
    • 对象成员变量;
    • 带实心菱形的实线,菱形指向整体
  • 依赖:是一种使用的关系,即一个类的实现需要另一个类的协助;
    • 局部变量、方法的参数或者对静态方法的调用
    • 带普通箭头的虚线,指向被使用者

各种关系的强弱顺序:

泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖


14、jdk 版本区别

JDK 8 新特性

  • Lambda 表达式:允许把函数作为一个方法的参数
  • 方法引用:可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
  • 默认方法:在接口里面有了一个实现的方法
  • 新编译工具:新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  • Stream API:新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中
  • Date Time API :加强对日期与时间的处理
  • Optional 类 :解决空指针异常。
  • Nashorn, JavaScript 引擎:允许我们在JVM上运行特定的javascript应用。

15、常见面试题

猜你喜欢

转载自blog.csdn.net/u013234928/article/details/89408403