关于java:Java基础知识点整理相当于一份题库

39次阅读

共计 28446 个字符,预计需要花费 72 分钟才能阅读完成。

看了网上很多对于 Java 根底知识点总结演绎整顿成题库的文章,然而感觉都不是很好,要么不全面,要么不精确,要么排版太乱了,所以明天整顿了一份 Java 根底知识点总结演绎整顿成题库,心愿对大家有帮忙哈~

因为本文篇幅过长,博主为了不便大家浏览和珍藏,特意将本文转成了一份 PDF 版的文档。

须要 PDF 版的敌人能够关注微信公众号:Java 团长 ,发送“ 基础知识”即可获取哈~

一、Java 概述

1、何为编程

编程就是让计算机为解决某个问题而应用某种程序设计语言编写程序代码,并最终失去后果的过程。

为了使计算机可能了解人的用意,人类就必须要将需解决的问题的思路、办法、和伎俩通过计算机可能了解的模式通知计算机,使得计算机可能依据人的指令一步一步去工作,实现某种特定的工作。这种人和计算机之间交换的过程就是编程。

2、什么是 Java

Java 是一门面向对象编程语言,不仅排汇了 C ++ 语言的各种长处,还摒弃了 C ++ 里难以了解的多继承、指针等概念,因而 Java 语言具备功能强大和简略易用两个特色。Java 语言作为动态面向对象编程语言的代表,极好地实现了面向对象实践,容许程序员以优雅的思维形式进行简单的编程。

3、jdk1.5 之后的三大版本

Java SE(J2SE,Java 2 Platform Standard Edition,标准版)
Java SE 以前称为 J2SE。它容许开发和部署在桌面、服务器、嵌入式环境和实时环境中应用的 Java 应用程序。Java SE 蕴含了反对 Java Web 服务开发的类,并为 Java EE 和 Java ME 提供根底。

Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)
Java EE 以前称为 J2EE。企业版本帮忙开发和部署可移植、强壮、可伸缩且平安的服务器端 Java 应用程序。Java EE 是在 Java SE 的根底上构建的,它提供 Web 服务、组件模型、治理和通信 API,能够用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0 应用程序。2018 年 2 月,Eclipse 发表正式将 JavaEE 更名为 JakartaEE

Java ME(J2ME,Java 2 Platform Micro Edition,微型版)
Java ME 以前称为 J2ME。Java ME 为在挪动设施和嵌入式设施(比方手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个强壮且灵便的环境。Java ME 包含灵便的用户界面、强壮的平安模型、许多内置的网络协议以及对能够动静下载的连网和离线应用程序的丰盛反对。基于 Java ME 标准的应用程序只需编写一次,就能够用于许多设施,而且能够利用每个设施的本机性能。

4、JVM、JRE 和 JDK 的关系

JVM
Java Virtual Machine 是 Java 虚拟机,Java 程序须要运行在虚拟机上,不同的平台有本人的虚拟机,因而 Java 语言能够实现跨平台。

JRE
Java Runtime Environment 包含 Java 虚拟机和 Java 程序所需的外围类库等。外围类库次要是 java.lang 包:蕴含了运行 Java 程序必不可少的零碎类,如根本数据类型、根本数学函数、字符串解决、线程、异样解决类等,零碎缺省加载这个包

如果想要运行一个开发好的 Java 程序,计算机中只须要装置 JRE 即可。

JDK
Java Development Kit 是提供给 Java 开发人员应用的,其中蕴含了 Java 的开发工具,也包含了 JRE。所以装置了 JDK,就无需再独自装置 JRE 了。其中的开发工具:编译工具 (javac.exe),打包工具(jar.exe) 等

JVM&JRE&JDK 关系图:

5、什么是跨平台性?原理是什么

所谓跨平台性,是指 java 语言编写的程序,一次编译后,能够在多个零碎平台上运行。

实现原理:Java 程序是通过 java 虚拟机在零碎平台上运行的,只有该零碎能够装置相应的 java 虚拟机,该零碎就能够运行 java 程序。

6、Java 语言有哪些特点

简略易学(Java 语言的语法与 C 语言和 C ++ 语言很靠近)

面向对象(封装,继承,多态)

平台无关性(Java 虚拟机实现平台无关性)

反对网络编程并且很不便(Java 语言诞生自身就是为简化网络编程设计的)

反对多线程(多线程机制使应用程序在同一时间并行执行多项任)

健壮性(Java 语言的强类型机制、异样解决、垃圾的主动收集等)

安全性

7、什么是字节码?采纳字节码的最大益处是什么

字节码:Java 源代码通过虚拟机编译器编译后产生的文件(即扩大为.class 的文件),它不面向任何特定的处理器,只面向虚拟机。

采纳字节码的益处:

Java 语言通过字节码的形式,在肯定水平上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比拟高效,而且,因为字节码并不专对一种特定的机器,因而,Java 程序毋庸从新编译便可在多种不同的计算机上运行。

先看下 java 中的编译器和解释器:

Java 中引入了虚拟机的概念,即在机器和编译程序之间退出了一层形象的虚构机器。这台虚构的机器在任何平台上都提供给编译程序一个的独特的接口。编译程序只须要面向虚拟机,生成虚拟机可能了解的代码,而后由解释器来将虚拟机代码转换为特定零碎的机器码执行。在 Java 中,这种供虚拟机了解的代码叫做字节码(即扩大为.class 的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,然而实现的虚拟机是雷同的。Java 源程序通过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,而后在特定的机器上运行,这就是下面提到的 Java 的特点的编译与解释并存的解释。

Java 源代码 —-> 编译器 —->jvm 可执行的 Java 字节码(即虚构指令)—->jvm—->jvm 中解释器 —–> 机器可执行的二进制机器码 —-> 程序运行。

8、什么是 Java 程序的主类?应用程序和小程序的主类有何不同?

一个程序中能够有多个类,但只能有一个类是主类。在 Java 应用程序中,这个主类是指蕴含 main()办法的类。而在 Java 小程序中,这个主类是一个继承自零碎类 JApplet 或 Applet 的子类。应用程序的主类不肯定要求是 public 类,但小程序的主类要求必须是 public 类。主类是 Java 程序执行的入口点。

9、Java 应用程序与小程序之间有那些差异?

简略说应用程序是从主线程启动 (也就是 main() 办法)。applet 小程序没有 main 办法,次要是嵌在浏览器页面上运行 (调用 init() 线程或者 run()来启动),嵌入浏览器这点跟 flash 的小游戏相似。

10、Java 和 C ++ 的区别

我晓得很多人没学过 C ++,然而面试官就是没事喜爱拿咱们 Java 和 C ++ 比呀!没方法!!!就算没学过 C ++,也要记下来!

  • 都是面向对象的语言,都反对封装、继承和多态
  • Java 不提供指针来间接拜访内存,程序内存更加平安
  • Java 的类是单继承的,C++ 反对多重继承;尽管 Java 的类不能够多继承,然而接口能够多继承。
  • Java 有主动内存管理机制,不须要程序员手动开释无用内存

11、Oracle JDK 和 OpenJDK 的比照

  1. Oracle JDK 版本将每三年公布一次,而 OpenJDK 版本每三个月公布一次;
  2. OpenJDK 是一个参考模型并且是齐全开源的,而 Oracle JDK 是 OpenJDK 的一个实现,并不是齐全开源的;
  3. Oracle JDK 比 OpenJDK 更稳固。OpenJDK 和 Oracle JDK 的代码简直雷同,但 Oracle JDK 有更多的类和一些谬误修复。因而,如果您想开发企业 / 商业软件,我建议您抉择 Oracle JDK,因为它通过了彻底的测试和稳固。某些状况下,有些人提到在应用 OpenJDK 可能会遇到了许多应用程序解体的问题,然而,只需切换到 Oracle JDK 就能够解决问题;
  4. 在响应性和 JVM 性能方面,Oracle JDK 与 OpenJDK 相比提供了更好的性能;
  5. Oracle JDK 不会为行将公布的版本提供长期反对,用户每次都必须通过更新到最新版本取得反对来获取最新版本;
  6. Oracle JDK 依据二进制代码许可协定取得许可,而 OpenJDK 依据 GPL v2 许可取得许可。

二、根底语法

1、数据类型

1. Java 有哪些数据类型

定义:Java 语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中调配了不同大小的内存空间。

分类

  • 根本数据类型

    • 数值型

      • 整数类型(byte,short,int,long)
      • 浮点类型(float,double)
    • 字符型(char)
    • 布尔型(boolean)
  • 援用数据类型

    • 类(class)
    • 接口(interface)
    • 数组([])

Java 根本数据类型图

2. switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上

在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也能够是 enum 类型,从 Java 7 开始,expr 还能够是字符串(String),然而长整型(long)在目前所有的版本中都是不能够的。

3. 用最有效率的办法计算 2 乘以 8

2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。

4. Math.round(11.5) 等于多少?Math.round(-11.5)等于多少

Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是 -11。四舍五入的原理是在参数上加 0.5 而后进行下取整。

5. float f=3.4; 是否正确

不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因而须要强制类型转换 float f =(float)3.4; 或者写成 float f =3.4F;。

6. short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1; 有错吗

对于 short s1 = 1; s1 = s1 + 1; 因为 1 是 int 类型,因而 s1+1 运算后果也是 int 型,须要强制转换类型能力赋值给 short 型。

而 short s1 = 1; s1 += 1; 能够正确编译,因为 s1+= 1; 相当于 s1 = (short(s1 + 1); 其中有隐含的强制类型转换。

2、编码

Java 语言采纳何种编码方案?有何特点?

Java 语言采纳 Unicode 编码标准,Unicode(规范码),它为每个字符制订了一个惟一的数值,因而在任何的语言,平台,程序都能够释怀的应用。

3、正文

1. 什么 Java 正文

定义:用于解释阐明程序的文字

分类

  • 单行正文
    格局:// 正文文字
  • 多行正文
    格局:/ 正文文字 /
  • 文档正文
    格局:/* 正文文字 /

作用

在程序中,尤其是简单的程序中,适当地退出正文能够减少程序的可读性,有利于程序的批改、调试和交换。正文的内容在程序编译的时候会被忽视,不会产生指标代码,正文的局部不会对程序的执行后果产生任何影响。

注意事项:多行和文档正文都不能嵌套应用。

4、拜访修饰符

1. 拜访修饰符 public,private,protected, 以及不写(默认)时的区别

定义:Java 中,能够应用拜访修饰符来爱护对类、变量、办法和构造方法的拜访。Java 反对 4 种不同的拜访权限。

分类

private : 在同一类内可见。应用对象:变量、办法。留神:不能润饰类(外部类)
default (即缺省,什么也不写,不应用任何关键字): 在同一包内可见,不应用任何修饰符。应用对象:类、接口、变量、办法。
protected : 对同一包内的类和所有子类可见。应用对象:变量、办法。留神:不能润饰类(外部类)。
public : 对所有类可见。应用对象:类、接口、变量、办法

拜访修饰符图

[图片上传失败 …(image-781999-1620016562516)]

5、运算符

& 和 && 的区别

& 运算符有两种用法:(1)按位与;(2)逻辑与。

&& 运算符是短路与运算。逻辑与跟短路与的差异是十分微小的,尽管二者都要求运算符左右两端的布尔值都是 true 整个表达式的值才是 true。&& 之所以称为短路运算,是因为如果 && 右边的表达式的值是 false,左边的表达式会被间接短路掉,不会进行运算。

留神:逻辑或运算符(|)和短路或运算符(||)的差异也是如此。

6、关键字

1. Java 有没有 goto

goto 是 Java 中的保留字,在目前版本的 Java 中没有应用。

2. final 有什么用?

用于润饰类、属性和办法;

  • 被 final 润饰的类不能够被继承
  • 被 final 润饰的办法不能够被重写
  • 被 final 润饰的变量不能够被扭转,被 final 润饰不可变的是变量的援用,而不是援用指向的内容,援用指向的内容是能够扭转的

3. final finally finalize 区别

  • final 能够润饰类、变量、办法,润饰类示意该类不能被继承、润饰办法示意该办法不能被重写、润饰变量示意该变量是一个常量不能被从新赋值。
  • finally 个别作用在 try-catch 代码块中,在解决异样的时候,通常咱们将肯定要执行的代码办法 finally 代码块中,示意不论是否出现异常,该代码块都会执行,个别用来寄存一些敞开资源的代码。
  • finalize 是一个办法,属于 Object 类的一个办法,而 Object 类是所有类的父类,该办法个别由垃圾回收器来调用,当咱们调用 System.gc() 办法的时候,由垃圾回收器调用 finalize(),回收垃圾,一个对象是否可回收的最初判断。

4. this 关键字的用法

this 是本身的一个对象,代表对象自身,能够了解为:指向对象自身的一个指针。

this 的用法在 java 中大体能够分为 3 种:

①. 一般的间接援用,this 相当于是指向以后对象自身。

②. 形参加成员名字重名,用 this 来辨别:

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}

③. 援用本类的构造函数

class Person{
    private String name;
    private int age;
    
    public Person() {}
 
    public Person(String name) {this.name = name;}
    public Person(String name, int age) {this(name);
        this.age = age;
    }
}

5. super 关键字的用法

super 能够了解为是指向本人超(父)类对象的一个指针,而这个超类指的是离本人最近的一个父类。

super 也有三种用法:

①. 一般的间接援用

与 this 相似,super 相当于是指向以后对象的父类的援用,这样就能够用 super.xxx 来援用父类的成员。

②. 子类中的成员变量或办法与父类中的成员变量或办法同名时,用 super 进行辨别

class Person{
    protected String name;
 
    public Person(String name) {this.name = name;}
 
}
 
class Student extends Person{
    private String name;
 
    public Student(String name, String name1) {super(name);
        this.name = name1;
    }
 
    public void getInfo(){System.out.println(this.name);      //Child
        System.out.println(super.name);     //Father
    }
 
}

public class Test {public static void main(String[] args) {Student s1 = new Student("Father","Child");
       s1.getInfo();}
}

③. 援用父类构造函数

  • super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
  • this(参数):调用本类中另一种模式的构造函数(应该为构造函数中的第一条语句)。

6. this 与 super 的区别

  • super: 它援用以后对象的间接父类中的成员(用来拜访间接父类中被暗藏的父类中成员数据或函数,基类与派生类中有雷同成员定义时如:super. 变量名 super. 成员函数据名(实参)
  • this:它代表以后对象名(在程序中易产生二义性之处,应应用 this 来指明以后对象;如果函数的形参加类中的成员数据同名,这时需用 this 来指明成员变量名)
  • super()和 this()相似, 区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
  • super()和 this()均需放在构造方法内第一行。
  • 只管能够用 this 调用一个结构器,但却不能调用两个。
  • this 和 super 不能同时呈现在一个构造函数外面,因为 this 必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数外面有雷同的语句,就失去了语句的意义,编译器也不会通过。
  • this()和 super()都指的是对象,所以,均不能够在 static 环境中应用。包含:static 变量,static 办法,static 语句块。
  • 从实质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字。

7. static 存在的次要意义

static 的次要意义是在于创立独立于具体对象的域变量或者办法。以致于即便没有创建对象,也能应用属性和调用办法!

static 关键字还有一个比拟要害的作用就是 用来造成动态代码块以优化程序性能。static 块能够置于类中的任何中央,类中能够有多个 static 块。在类首次被加载的时候,会依照 static 块的程序来执行每个 static 块,并且只会执行一次。

为什么说 static 块能够用来优化程序性能,是因为它的个性: 只会在类加载的时候执行一次。因而,很多时候会将一些只须要进行一次的初始化操作都放在 static 代码块中进行。

8. static 的独特之处

  • 被 static 润饰的变量或者办法是独立于该类的任何对象,也就是说,这些变量和办法不属于任何一个实例对象,而是被类的实例对象所共享。

怎么了解“被类的实例对象所共享”这句话呢?就是说,一个类的动态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,咱们都晓得一个类能够创立多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我感觉我曾经讲的很艰深了,你明确了咩?

  • 在该类被第一次加载的时候,就会去加载被 static 润饰的局部,而且只在类第一次应用时加载并进行初始化,留神这是第一次用就要初始化,前面依据须要是能够再次赋值的。
  • static 变量值在类加载的时候调配空间,当前创立类对象的时候不会重新分配。赋值的话,是能够任意赋值的!
  • 被 static 润饰的变量或者办法是优先于对象存在的,也就是说当一个类加载结束之后,即使没有创建对象,也能够去拜访。

9. static 利用场景

因为 static 是被类的实例对象所共享,因而如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为动态变量。

因而比拟常见的 static 利用场景有:

  • 润饰成员变量
  • 润饰成员办法
  • 动态代码块
  • 润饰类【只能润饰外部类也就是动态外部类】
  • 动态导包

10. static 注意事项

  1. 动态只能拜访动态。
  2. 非动态既能够拜访非动态的,也能够拜访动态的。

7、流程管制语句

1. break ,continue ,return 的区别及作用

break 跳出总上一层循环,不再执行循环(完结以后的循环体)

continue 跳出本次循环,继续执行下次循环(完结正在执行的循环 进入下一个循环条件)

return 程序返回,不再执行上面的代码(完结以后的办法 间接返回)

2. 在 Java 中,如何跳出以后的多重嵌套循环

在 Java 中,要想跳出多重循环,能够在里面的循环语句前定义一个标号,而后在里层循环体的代码中应用带有标号的 break 语句,即可跳出外层循环。例如:

public static void main(String[] args) {
    ok:
    for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; j++) {System.out.println("i=" + i + ",j=" + j);
            if (j == 5) {break ok;}

        }
    }
}

三、面向对象

1、面向对象概述

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

面向过程:

长处:性能比面向对象高,因为类调用时须要实例化,开销比拟大,比拟耗费资源; 比方单片机、嵌入式开发、Linux/Unix 等个别采纳面向过程开发,性能是最重要的因素。

毛病:没有面向对象易保护、易复用、易扩大

面向对象:

长处:易保护、易复用、易扩大,因为面向对象有封装、继承、多态性的个性,能够设计出低耦合的零碎,使零碎更加灵便、更加易于保护

毛病:性能比面向过程低

面向过程是具体化的,流程化的,解决一个问题,你须要一步一步的剖析,一步一步的实现。

面向对象是模型化的,你只需形象出一个类,这是一个关闭的盒子,在这里你领有数据也领有解决问题的办法。须要什么性能间接应用就能够了,不用去一步一步的实现,至于这个性能是如何实现的,管咱们什么事?咱们会用就能够了。

面向对象的底层其实还是面向过程,把面向过程形象成类,而后封装,不便咱们应用的就是面向对象了。

2、面向对象三大个性

1. 面向对象的特色有哪些方面

面向对象的特色次要有以下几个方面:

形象:形象是将一类对象的独特特色总结进去结构类的过程,包含数据抽象和行为形象两方面。形象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

封装

封装把一个对象的属性私有化,同时提供一些能够被外界拜访的属性的办法,如果属性不想被外界拜访,咱们大可不必提供办法给外界拜访。然而如果一个类没有提供给外界拜访的办法,那么这个类也没有什么意义了。

继承

继承是应用已存在的类的定义作为根底建设新类的技术,新类的定义能够减少新的数据或新的性能,也能够用父类的性能,但不能选择性地继承父类。通过应用继承咱们可能十分不便地复用以前的代码。

对于继承如下 3 点请记住:

  1. 子类领有父类非 private 的属性和办法。
  2. 子类能够领有本人属性和办法,即子类能够对父类进行扩大。
  3. 子类能够用本人的形式实现父类的办法。(当前介绍)。

多态

所谓多态就是指程序中定义的援用变量所指向的具体类型和通过该援用变量收回的办法调用在编程时并不确定,而是在程序运行期间才确定,即一个援用变量到底会指向哪个类的实例对象,该援用变量收回的办法调用到底是哪个类中实现的办法,必须在由程序运行期间能力决定。

在 Java 中有两种模式能够实现多态:继承(多个子类对同一办法的重写)和接口(实现接口并笼罩接口中同一办法)。

其中 Java 面向对象编程三大个性:封装 继承 多态

封装:暗藏对象的属性和实现细节,仅对外提供公共拜访形式,将变动隔离,便于应用,进步复用性和安全性。

继承:继承是应用已存在的类的定义作为根底建设新类的技术,新类的定义能够减少新的数据或新的性能,也能够用父类的性能,但不能选择性地继承父类。通过应用继承能够进步代码复用性。继承是多态的前提。

对于继承如下 3 点请记住:

  1. 子类领有父类非 private 的属性和办法。
  2. 子类能够领有本人属性和办法,即子类能够对父类进行扩大。
  3. 子类能够用本人的形式实现父类的办法。

多态性:父类或接口定义的援用变量能够指向子类或具体实现类的实例对象。进步了程序的拓展性。

在 Java 中有两种模式能够实现多态:继承(多个子类对同一办法的重写)和接口(实现接口并笼罩接口中同一办法)。

办法重载(overload)实现的是编译时的多态性(也称为前绑定),而办法重写(override)实现的是运行时的多态性(也称为后绑定)。

一个援用变量到底会指向哪个类的实例对象,该援用变量收回的办法调用到底是哪个类中实现的办法,必须在由程序运行期间能力决定。运行时的多态是面向对象最精华的货色,要实现多态须要做两件事:

  • 办法重写(子类继承父类并重写父类中已有的或形象的办法);
  • 对象造型(用父类型援用子类型对象,这样同样的援用调用同样的办法就会依据子类对象的不同而体现出不同的行为)。

2. 什么是多态机制?Java 语言是如何实现多态的?

所谓多态就是指程序中定义的援用变量所指向的具体类型和通过该援用变量收回的办法调用在编程时并不确定,而是在程序运行期间才确定,即一个援用变量倒底会指向哪个类的实例对象,该援用变量收回的办法调用到底是哪个类中实现的办法,必须在由程序运行期间能力决定。因为在程序运行时才确定具体的类,这样,不必批改源程序代码,就能够让援用变量绑定到各种不同的类实现上,从而导致该援用调用的具体方法随之扭转,即不批改程序代码就能够扭转程序运行时所绑定的具体代码,让程序能够抉择多个运行状态,这就是多态性。

多态分为编译时多态和运行时多态。其中编辑时多态是动态的,次要是指办法的重载,它是依据参数列表的不同来辨别不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动静的,它是通过动静绑定来实现的,也就是咱们所说的多态性。

多态的实现

Java 实现多态有三个必要条件:继承、重写、向上转型。

继承:在多态中必须存在有继承关系的子类和父类。

重写:子类对父类中某些办法进行从新定义,在调用这些办法时就会调用子类的办法。

向上转型:在多态中须要将子类的援用赋给父类对象,只有这样该援用才可能具备技能调用父类的办法和子类的办法。

只有满足了上述三个条件,咱们才可能在同一个继承构造中应用对立的逻辑实现代码解决不同的对象,从而达到执行不同的行为。

对于 Java 而言,它多态的实现机制遵循一个准则:当超类对象援用变量援用子类对象时,被援用对象的类型而不是援用变量的类型决定了调用谁的成员办法,然而这个被调用的办法必须是在超类中定义过的,也就是说被子类笼罩的办法。

3. 面向对象五大根本准则是什么(可选)

  • 繁多职责准则 SRP(Single Responsibility Principle)

类的性能要繁多,不能无所不包,跟杂货铺似的。

  • 凋谢关闭准则 OCP(Open-Close Principle)

一个模块对于拓展是凋谢的,对于批改是关闭的,想要减少性能热烈欢迎,想要批改,哼,一万个不乐意。

  • 里式替换准则 LSP(the Liskov Substitution Principle LSP)

子类能够替换父类呈现在父类可能呈现的任何中央。比方你能代表你爸去你姥姥家干活。哈哈~~

  • 依赖倒置准则 DIP(the Dependency Inversion Principle DIP)

高层次的模块不应该依赖于低层次的模块,他们都应该依赖于形象。形象不应该依赖于具体实现,具体实现应该依赖于形象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是形象的,上面有具体的 xx 省,xx 市,xx 县。你要依赖的形象是中国人,而不是你是 xx 村的。

  • 接口拆散准则 ISP(the Interface Segregation Principle ISP)

设计时采纳多个与特定客户类无关的接口比采纳一个通用的接口要好。就比方一个手机领有打电话,看视频,玩游戏等性能,把这几个性能拆分成不同的接口,比在一个接口里要好的多。

3、类与接口

1. 抽象类和接口的比照

抽象类是用来捕获子类的通用个性的。接口是形象办法的汇合。

从设计层面来说,抽象类是对类的形象,是一种模板设计,接口是行为的形象,是一种行为的标准。

相同点

接口和抽象类都不能实例化
都位于继承的顶端,用于被其余实现或继承
都蕴含形象办法,其子类都必须覆写这些形象办法

不同点

备注:Java8 中接口中引入默认办法和静态方法,以此来缩小抽象类和接口之间的差别。

当初,咱们能够为接口提供默认实现的办法了,并且不必强制子类来实现它。

接口和抽象类各有优缺点,在接口和抽象类的抉择上,必须恪守这样一个准则:

  • 行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
  • 抉择抽象类的时候通常是如下状况:须要定义子类的行为,又要为子类提供通用的性能。

2. 一般类和抽象类有哪些区别?

  • 一般类不能蕴含形象办法,抽象类能够蕴含形象办法。
  • 抽象类不能间接实例化,一般类能够间接实例化。

3. 抽象类能应用 final 润饰吗?

不能,定义抽象类就是让其余类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能润饰抽象类

4. 创立一个对象用什么关键字?对象实例与对象援用有何不同?

new 关键字,new 创建对象实例(对象实例在堆内存中),对象援用指向对象实例(对象援用寄存在栈内存中)。一个对象援用能够指向 0 个或 1 个对象(一根绳子能够不系气球,也能够系一个气球); 一个对象能够有 n 个援用指向它(能够用 n 条绳子系住一个气球)

4、变量与办法

1. 成员变量与局部变量的区别有哪些

变量:在程序执行的过程中,在某个范畴内其值能够产生扭转的量。从实质上讲,变量其实是内存中的一小块区域

成员变量:办法内部,类外部定义的变量

局部变量:类的办法中的变量。

成员变量和局部变量的区别

作用域

成员变量:针对整个类无效。
局部变量:只在某个范畴内无效。(个别指的就是办法, 语句体内)

存储地位

成员变量:随着对象的创立而存在,随着对象的隐没而隐没,存储在堆内存中。
局部变量:在办法被调用,或者语句被执行的时候存在,存储在栈内存中。当办法调用完,或者语句完结后,就主动开释。

生命周期

成员变量:随着对象的创立而存在,随着对象的隐没而隐没
局部变量:当办法调用完,或者语句完结后,就主动开释。

初始值

成员变量:有默认初始值。

局部变量:没有默认初始值,应用前必须赋值。

应用准则

在应用变量时须要遵循的准则为:就近准则
首先在部分范畴找,有就应用;接着在成员地位找。

2. 在 Java 中定义一个不做事且没有参数的构造方法的作用

Java 程序在执行子类的构造方法之前,如果没有用 super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因而,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super()来调用父类中特定的构造方法,则编译时将产生谬误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。

3. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目标是?

帮忙子类做初始化工作。

4. 一个类的构造方法的作用是什么?若一个类没有申明构造方法,改程序能正确执行吗?为什么?

次要作用是实现对类对象的初始化工作。能够执行。因为一个类即便没有申明构造方法也会有默认的不带参数的构造方法。

5. 构造方法有哪些个性?

名字与类名雷同;

没有返回值,但不能用 void 申明构造函数;

生成类的对象时主动执行,无需调用。

6. 动态变量和实例变量区别

动态变量:动态变量因为不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM 只为动态变量调配一次内存空间。

实例变量:每次创建对象,都会为每个对象调配成员变量内存空间,实例变量是属于实例对象的,在内存中,创立几次对象,就有几份成员变量。

7. 动态变量与一般变量区别

static 变量也称作动态变量,动态变量和非动态变量的区别是:动态变量被所有的对象所共享,在内存中只有一个正本,它当且仅当在类首次加载时会被初始化。而非动态变量是对象所领有的,在创建对象的时候被初始化,存在多个正本,各个对象领有的正本互不影响。

还有一点就是 static 成员变量的初始化程序依照定义的程序进行初始化。

8. 静态方法和实例办法有何不同?

静态方法和实例办法的区别次要体现在两个方面:

  1. 在内部调用静态方法时,能够应用 ” 类名. 办法名 ” 的形式,也能够应用 ” 对象名. 办法名 ” 的形式。而实例办法只有前面这种形式。也就是说,调用静态方法能够无需创建对象。
  2. 静态方法在拜访本类的成员时,只容许拜访动态成员(即动态成员变量和静态方法),而不容许拜访实例成员变量和实例办法;实例办法则无此限度

9. 在一个静态方法内调用一个非动态成员为什么是非法的?

因为静态方法能够不通过对象进行调用,因而在静态方法里,不能调用其余非动态变量,也不能够拜访非动态变量成员。

10. 什么是办法的返回值?返回值的作用是什么?

办法的返回值是指咱们获取到的某个办法体中的代码执行后产生的后果!(前提是该办法可能产生后果)。返回值的作用: 接管出后果,使得它能够用于其余的操作!

5、外部类

1. 什么是外部类?

在 Java 中,能够将一个类的定义放在另外一个类的定义外部,这就是外部类。外部类自身就是类的一个属性,与其余属性定义形式统一。

2. 外部类的分类有哪些

外部类能够分为四种:成员外部类、部分外部类、匿名外部类和动态外部类。

动态外部类

定义在类外部的动态类,就是动态外部类。

public class Outer {

    private static int radius = 1;

    static class StaticInner {public void visit() {System.out.println("visit outer static  variable:" + radius);
        }
    }
}

动态外部类能够拜访外部类所有的动态变量,而不可拜访外部类的非动态变量;动态外部类的创立形式,new 外部类. 动态外部类(),如下:

Outer.StaticInner inner = new Outer.StaticInner();
inner.visit();

成员外部类

定义在类外部,成员地位上的非动态类,就是成员外部类。

public class Outer {

    private static  int radius = 1;
    private int count =2;
    
     class Inner {public void visit() {System.out.println("visit outer static  variable:" + radius);
            System.out.println("visit outer   variable:" + count);
        }
    }
}

成员外部类能够拜访外部类所有的变量和办法,包含动态和非动态,公有和私有。成员外部类依赖于外部类的实例,它的创立形式 外部类实例.new 外部类(),如下:

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.visit();

部分外部类

定义在办法中的外部类,就是部分外部类。

public class Outer {

    private  int out_a = 1;
    private static int STATIC_b = 2;

    public void testFunctionClass(){
        int inner_c =3;
        class Inner {private void fun(){System.out.println(out_a);
                System.out.println(STATIC_b);
                System.out.println(inner_c);
            }
        }
        Inner  inner = new Inner();
        inner.fun();}
    public static void testStaticFunctionClass(){
        int d =3;
        class Inner {private void fun(){// System.out.println(out_a); 编译谬误,定义在静态方法中的部分类不能够拜访外部类的实例变量
                System.out.println(STATIC_b);
                System.out.println(d);
            }
        }
        Inner  inner = new Inner();
        inner.fun();}
}

定义在实例办法中的部分类能够拜访外部类的所有变量和办法,定义在静态方法中的部分类只能拜访外部类的动态变量和办法。部分外部类的创立形式,在对应办法内,new 外部类(),如下:

 public static void testStaticFunctionClass(){class Inner {}
    Inner  inner = new Inner();}

匿名外部类

匿名外部类就是没有名字的外部类,日常开发中应用的比拟多。

public class Outer {private void test(final int i) {new Service() {public void method() {for (int j = 0; j < i; j++) {System.out.println("匿名外部类");
                }
            }
        }.method();}
 }
 // 匿名外部类必须继承或实现一个已有的接口 
 interface Service{void method();
}
 }

除了没有名字,匿名外部类还有以下特点:

  • 匿名外部类必须继承一个抽象类或者实现一个接口。
  • 匿名外部类不能定义任何动态成员和静态方法。
  • 当所在的办法的形参须要被匿名外部类应用时,必须申明为 final。
  • 匿名外部类不能是形象的,它必须要实现继承的类或者实现的接口的所有形象办法。

匿名外部类创立形式:

new 类 / 接口{// 匿名外部类实现局部}

3. 外部类的长处

咱们为什么要应用外部类呢?因为它有以下长处:

  • 一个外部类对象能够拜访创立它的外部类对象的内容,包含公有数据!
  • 外部类不为同一包的其余类所见,具备很好的封装性;
  • 外部类无效实现了“多重继承”,优化 java 单继承的缺点。
  • 匿名外部类能够很不便的定义回调。

4. 外部类有哪些利用场景

  1. 一些多算法场合
  2. 解决一些非面向对象的语句块。
  3. 适当应用外部类,使得代码更加灵便和富裕扩展性。
  4. 当某个类除了它的外部类,不再被其余的类应用时。

5. 部分外部类和匿名外部类拜访局部变量的时候,为什么变量必须要加上 final?

部分外部类和匿名外部类拜访局部变量的时候,为什么变量必须要加上 final 呢?它外部原理是什么呢?

先看这段代码:

public class Outer {void outMethod(){
        final int a =10;
        class Inner {void innerMethod(){System.out.println(a);
            }

        }
    }
}

以上例子,为什么要加 final 呢?是因为生命周期不统一,局部变量间接存储在栈中,当办法执行完结后,非 final 的局部变量就被销毁。而部分外部类对局部变量的援用仍然存在,如果部分外部类要调用局部变量时,就会出错。加了 final,能够确保部分外部类应用的变量与外层的局部变量辨别开,解决了这个问题。

6. 外部类相干,看程序说出运行后果

public class Outer {
    private int age = 12;

    class Inner {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部变量:" + age);
            System.out.println("外部类变量:" + this.age);
            System.out.println("外部类变量:" + Outer.this.age);
        }
    }

    public static void main(String[] args) {Outer.Inner in = new Outer().new Inner();
        in.print();}

}

运行后果:

局部变量:14
外部类变量:13
外部类变量:12

6、重写与重载

1. 结构器(constructor)是否可被重写(override)

结构器不能被继承,因而不能被重写,但能够被重载。

2. 重载(Overload)和重写(Override)的区别。重载的办法是否依据返回类型进行辨别?

办法的重载和重写都是实现多态的形式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载:产生在同一个类中,办法名雷同参数列表不同(参数类型不同、个数不同、程序不同),与办法返回值和拜访修饰符无关,即重载的办法不能依据返回类型进行辨别

重写:产生在父子类中,办法名、参数列表必须雷同,返回值小于等于父类,抛出的异样小于等于父类,拜访修饰符大于等于父类(里氏代换准则);如果父类办法拜访修饰符为 private 则子类中就不是重写。

7、对象相等判断

1. == 和 equals 的区别是什么

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(根本数据类型 == 比拟的是值,援用数据类型 == 比拟的是内存地址)

equals() : 它的作用也是判断两个对象是否相等。但它个别有两种应用状况:

状况 1:类没有笼罩 equals() 办法。则通过 equals() 比拟该类的两个对象时,等价于通过“==”比拟这两个对象。

状况 2:类笼罩了 equals() 办法。个别,咱们都笼罩 equals() 办法来两个对象的内容相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。

举个例子:

public class test1 {public static void main(String[] args) {String a = new String("ab"); // a 为一个援用
        String b = new String("ab"); // b 为另一个援用, 对象的内容一样
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 从常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一对象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

阐明:

String 中的 equals 办法是被重写过的,因为 object 的 equals 办法是比拟的对象的内存地址,而 String 的 equals 办法比拟的是对象的值。
当创立 String 类型的对象时,虚构机会在常量池中查找有没有曾经存在的值和要创立的值雷同的对象,如果有就把它赋给以后援用。如果没有就在常量池中从新创立一个 String 对象。

2. hashCode 与 equals (重要)

HashSet 如何查看反复

两个对象的 hashCode() 雷同,则 equals() 也肯定为 true,对吗?

hashCode 和 equals 办法的关系

面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 办法?”

hashCode()介绍

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引地位。hashCode() 定义在 JDK 的 Object.java 中,这就意味着 Java 中的任何类都蕴含有 hashCode()函数。

散列表存储的是键值对(key-value),它的特点是:能依据“键”疾速的检索出对应的“值”。这其中就利用到了散列码!(能够疾速找到所须要的对象)

为什么要有 hashCode

咱们以“HashSet 如何查看反复”为例子来阐明为什么要有 hashCode:

当你把对象退出 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象退出的地位,同时也会与其余曾经退出的对象的 hashcode 值作比拟,如果没有相符的 hashcode,HashSet 会假如对象没有反复呈现。然而如果发现有雷同 hashcode 值的对象,这时会调用 equals()办法来查看 hashcode 相等的对象是否真的雷同。如果两者雷同,HashSet 就不会让其退出操作胜利。如果不同的话,就会从新散列到其余地位。(摘自我的 Java 启蒙书《Head first java》第二版)。这样咱们就大大减少了 equals 的次数,相应就大大提高了执行速度。

hashCode()与 equals()的相干规定

如果两个对象相等,则 hashcode 肯定也是雷同的

两个对象相等,对两个对象别离调用 equals 办法都返回 true

两个对象有雷同的 hashcode 值,它们也不肯定是相等的

因而,equals 办法被笼罩过,则 hashCode 办法也必须被笼罩

hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即便这两个对象指向雷同的数据)

8、值传递

1. 当一个对象被当作参数传递到一个办法后,此办法可扭转这个对象的属性,并可返回变动后的后果,那么这里到底是值传递还是援用传递

是值传递。Java 语言的办法调用只反对参数的值传递。当一个对象实例作为一个参数被传递到办法中时,参数的值就是对该对象的援用。对象的属性能够在被调用过程中被扭转,但对对象援用的扭转是不会影响到调用者的

2. 为什么 Java 中只有值传递

首先回顾一下在程序设计语言中无关将参数传递给办法(或函数)的一些专业术语。按值调用 (call by value) 示意办法接管的是调用者提供的值,而按援用调用(call by reference)示意办法接管的是调用者提供的变量地址。一个办法能够批改传递援用所对应的变量值,而不能批改传递值调用所对应的变量值。它用来形容各种程序设计语言(不只是 Java)中办法参数传递形式。

Java 程序设计语言总是采纳按值调用。也就是说,办法失去的是所有参数值的一个拷贝,也就是说,办法不能批改传递给它的任何参数变量的内容。

上面通过 3 个例子来给大家阐明

example 1

public static void main(String[] args) {
    int num1 = 10;
    int num2 = 20;

    swap(num1, num2);

    System.out.println("num1 =" + num1);
    System.out.println("num2 =" + num2);
}

public static void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;

    System.out.println("a =" + a);
    System.out.println("b =" + b);
}

后果:

a = 20
b = 10
num1 = 10
num2 = 20

解析:

在 swap 办法中,a、b 的值进行替换,并不会影响到 num1、num2。因为,a、b 中的值,只是从 num1、num2 的复制过去的。也就是说,a、b 相当于 num1、num2 的正本,正本的内容无论怎么批改,都不会影响到原件自身。

通过下面例子,咱们曾经晓得了一个办法不能批改一个根本数据类型的参数,而对象援用作为参数就不一样,请看 example2.

example 2

public static void main(String[] args) {int[] arr = {1, 2, 3, 4, 5};
        System.out.println(arr[0]);
        change(arr);
        System.out.println(arr[0]);
    }

    public static void change(int[] array) {
        // 将数组的第一个元素变为 0
        array[0] = 0;
    }

后果:

1
0

解析:

array 被初始化 arr 的拷贝也就是一个对象的援用,也就是说 array 和 arr 指向的时同一个数组对象。因而,内部对援用对象的扭转会反映到所对应的对象上。

通过 example2 咱们曾经看到,实现一个扭转对象参数状态的办法并不是一件难事。理由很简略,办法失去的是对象援用的拷贝,对象援用及其他的拷贝同时援用同一个对象。

很多程序设计语言(特地是,C++ 和 Pascal)提供了两种参数传递的形式:值调用和援用调用。有些程序员(甚至本书的作者)认为 Java 程序设计语言对对象采纳的是援用调用,实际上,这种了解是不对的。因为这种误会具备肯定的普遍性,所以上面给出一个反例来具体地论述一下这个问题。

example 3

public class Test {public static void main(String[] args) {
        // TODO Auto-generated method stub
        Student s1 = new Student("小张");
        Student s2 = new Student("小李");
        Test.swap(s1, s2);
        System.out.println("s1:" + s1.getName());
        System.out.println("s2:" + s2.getName());
    }

    public static void swap(Student x, Student y) {
        Student temp = x;
        x = y;
        y = temp;
        System.out.println("x:" + x.getName());
        System.out.println("y:" + y.getName());
    }
}

后果:

x: 小李
y: 小张
s1: 小张
s2: 小李

解析:

替换之前:

替换之后:

通过下面两张图能够很清晰的看出:办法并没有扭转存储在变量 s1 和 s2 中的对象援用。swap 办法的参数 x 和 y 被初始化为两个对象援用的拷贝,这个办法替换的是这两个拷贝

总结

Java 程序设计语言对对象采纳的不是援用调用,实际上,对象援用是按值传递的。

上面再总结一下 Java 中办法参数的应用状况:

  • 一个办法不能批改一个根本数据类型的参数(即数值型或布尔型》
  • 一个办法能够扭转一个对象参数的状态。
  • 一个办法不能让对象参数援用一个新的对象。

3. 值传递和援用传递有什么区别

值传递:指的是在办法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相干了。

援用传递:指的是在办法调用时,传递的参数是按援用进行传递,其实传递的援用的地址,也就是变量所对应的内存空间的地址。传递的是值的援用,也就是说传递前和传递后都指向同一个援用(也就是同一个内存空间)。

9、Java 包

1. JDK 中罕用的包有哪些

  • java.lang:这个是零碎的根底类;
  • java.io:这外面是所有输入输出无关的类,比方文件操作等;
  • java.nio:为了欠缺 io 包中的性能,进步 io 包中性能而写的一个新包;
  • java.net:这外面是与网络无关的类;
  • java.util:这个是零碎辅助类,特地是汇合类;
  • java.sql:这个是数据库操作的类。

2. import java 和 javax 有什么区别

刚开始的时候 JavaAPI 所必须的包是 java 结尾的包,javax 过后只是扩大 API 包来说应用。然而随着工夫的推移,javax 逐步的扩大成为 Java API 的组成部分。然而,将扩大从 javax 包挪动到 java 包将是太麻烦了,最终会毁坏一堆现有的代码。因而,最终决定 javax 包将成为规范 API 的一部分。

所以,实际上 java 和 javax 没有区别。这都是一个名字。

四、IO 流

1、java 中 IO 流分为几种?

  • 依照流的流向分,能够分为输出流和输入流;
  • 依照操作单元划分,能够划分为字节流和字符流;
  • 依照流的角色划分为节点流和解决流。

Java Io 流共波及 40 多个类,这些类看上去很芜杂,但实际上很有规定,而且彼此之间存在十分严密的分割,Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生进去的。

  • InputStream/Reader: 所有的输出流的基类,前者是字节输出流,后者是字符输出流。
  • OutputStream/Writer: 所有输入流的基类,前者是字节输入流,后者是字符输入流。

按操作形式分类结构图:

按操作对象分类结构图:

2、BIO,NIO,AIO 有什么区别?

简答

  • BIO:Block IO 同步阻塞式 IO,就是咱们平时应用的传统 IO,它的特点是模式简略使用方便,并发解决能力低。
  • NIO:Non IO 同步非阻塞 IO,是传统 IO 的降级,客户端和服务器端通过 Channel(通道)通信,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的降级,也叫 NIO2,实现了异步非梗塞 IO,异步 IO 的操作基于事件和回调机制。

具体答复

  • BIO (Blocking I/O): 同步阻塞 I / O 模式,数据的读取写入必须阻塞在一个线程内期待其实现。在流动连接数不是特地高(小于单机 1000)的状况下,这种模型是比拟不错的,能够让每一个连贯专一于本人的 I/O 并且编程模型简略,也不必过多思考零碎的过载、限流等问题。线程池自身就是一个人造的漏斗,能够缓冲一些零碎解决不了的连贯或申请。然而,当面对十万甚至百万级连贯的时候,传统的 BIO 模型是无能为力的。因而,咱们须要一种更高效的 I/O 解决模型来应答更高的并发量。
  • NIO (New I/O): NIO 是一种同步非阻塞的 I / O 模型,在 Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等形象。NIO 中的 N 能够了解为 Non-blocking,不单纯是 New。它反对面向缓冲的,基于通道的 I / O 操作方法。NIO 提供了与传统 BIO 模型中的 Socket 和 ServerSocket 绝对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现, 两种通道都反对阻塞和非阻塞两种模式。阻塞模式应用就像传统中的反对一样,比较简单,然而性能和可靠性都不好;非阻塞模式正好与之相同。对于低负载、低并发的应用程序,能够应用同步阻塞 I / O 来晋升开发速率和更好的维护性;对于高负载、高并发的(网络)利用,应应用 NIO 的非阻塞模式来开发
  • AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2, 它是异步非阻塞的 IO 模型。异步 IO 是基于事件和回调机制实现的,也就是利用操作之后会间接返回,不会梗塞在那里,当后盾解决实现,操作系统会告诉相应的线程进行后续的操作。AIO 是异步 IO 的缩写,尽管 NIO 在网络操作中,提供了非阻塞的办法,然而 NIO 的 IO 行为还是同步的。对于 NIO 来说,咱们的业务线程是在 IO 操作筹备好时,失去告诉,接着就由这个线程自行进行 IO 操作,IO 操作自身是同步的。查阅网上相干材料,我发现就目前来说 AIO 的利用还不是很宽泛,Netty 之前也尝试应用过 AIO,不过又放弃了。

3、Files 的罕用办法都有哪些?

  • Files. exists():检测文件门路是否存在。
  • Files. createFile():创立文件。
  • Files. createDirectory():创立文件夹。
  • Files. delete():删除一个文件或目录。
  • Files. copy():复制文件。
  • Files. move():挪动文件。
  • Files. size():查看文件个数。
  • Files. read():读取文件。
  • Files. write():写入文件。

五、反射

1、什么是反射机制?

JAVA 反射机制是在运行状态中,对于任意一个类,都可能晓得这个类的所有属性和办法;对于任意一个对象,都可能调用它的任意一个办法和属性;这种动静获取的信息以及动静调用对象的办法的性能称为 java 语言的反射机制。

动态编译和动静编译

动态编译:在编译时确定类型,绑定对象
动静编译:运行时确定类型,绑定对象

2、反射机制优缺点

  • 长处:运行期类型的判断,动静加载类,进步代码灵便度。
  • 毛病:性能瓶颈:反射相当于一系列解释操作,告诉 JVM 要做的事件,性能比间接的 java 代码要慢很多。

3、反射机制的利用场景有哪些?

反射是框架设计的灵魂。

在咱们平时的我的项目开发过程中,基本上很少会间接应用到反射机制,但这不能阐明反射机制没有用,实际上有很多设计、开发都与反射机制无关,例如模块化的开发,通过反射去调用对应的字节码;动静代理设计模式也采纳了反射机制,还有咱们日常应用的 Spring/Hibernate 等框架也大量应用到了反射机制。

举例:①咱们在应用 JDBC 连贯数据库时应用 Class.forName()通过反射加载数据库的驱动程序;②Spring 框架也用到很多反射机制,最经典的就是 xml 的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中; 2)Java 类外面解析 xml 或 properties 外面的内容,失去对应实体类的字节码字符串以及相干的属性信息; 3)应用反射机制,依据这个字符串取得某个类的 Class 实例; 4)动静配置实例的属性

4、Java 获取反射的三种办法

1. 通过 new 对象实现反射机制

2. 通过门路实现反射机制

3. 通过类名实现反射机制

public class Student {
    private int id;
    String name;
    protected boolean sex;
    public float score;
}
public class Get {
    // 获取反射机制三种形式
    public static void main(String[] args) throws ClassNotFoundException {// 形式一(通过建设对象)
        Student stu = new Student();
        Class classobj1 = stu.getClass();
        System.out.println(classobj1.getName());
        // 形式二(所在通过门路 - 相对路径)Class classobj2 = Class.forName("fanshe.Student");
        System.out.println(classobj2.getName());
        // 形式三(通过类名)Class classobj3 = Student.class;
        System.out.println(classobj3.getName());
    }
}

六、网络编程

网络编程的能够查看这篇文章:https://thinkwon.blog.csdn.net/article/details/104390612

内容不仅包含 TCP/IP 协定和三次握手四次挥手的常识,还包含计算机网络体系结构,HTTP 协定,get 申请和 post 申请区别,session 和 cookie 的区别等,欢送大家浏览。

七、罕用 API

1、String 相干

1. 字符型常量和字符串常量的区别

  • 模式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
  • 含意上: 字符常量相当于一个整形值(ASCII 值), 能够加入表达式运算 字符串常量代表一个地址值(该字符串在内存中寄存地位)
  • 占内存大小:字符常量只占一个字节 字符串常量占若干个字节(至多一个字符完结标记)

2. 什么是字符串常量池?

字符串常量池位于堆内存中,专门用来存储字符串常量,能够进步内存的使用率,防止开拓多块空间存储雷同的字符串,在创立字符串时 JVM 会首先查看字符串常量池,如果该字符串曾经存在池中,则返回它的援用,如果不存在,则实例化一个字符串放到池中,并返回其援用。

3. String 是最根本的数据类型吗?

不是。Java 中的根本数据类型只有 8 个:byte、short、int、long、float、double、char、boolean;除了根本类型(primitive type),剩下的都是援用类型(referencetype),Java 5 当前引入的枚举类型也算是一种比拟非凡的援用类型。

这是很根底的货色,然而很多初学者却容易漠视,Java 的 8 种根本数据类型中不包含 String,根本数据类型中用来形容文本数据的是 char,然而它只能示意单个字符,比方‘a’,‘好’之类的,如果要形容一段文本,就须要用多个 char 类型的变量,也就是一个 char 类型数组,比方“你好”就是长度为 2 的数组 char[] chars = {‘你’,‘好’};

然而应用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是应用的时候开发者不须要间接操作底层数组,用更加简便的形式即可实现对字符串的应用。

4. String 有哪些个性

不变性:String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创立一个新的对象,再把援用指向该对象。不变模式的次要作用在于当一个对象须要被多线程共享并频繁拜访时,能够保证数据的一致性。

常量池优化:String 对象创立之后,会在字符串常量池中进行缓存,如果下次创立同样的对象时,会间接返回缓存的援用。

final:应用 final 来定义 String 类,示意 String 类不能被继承,进步了零碎的安全性。

5. String 为什么是不可变的吗?

简略来说就是 String 类利用了 final 润饰的 char 类型数组存储字符,源码如下图所以:

/** The value is used for character storage. */
private final char value[];

6. String 真的是不可变的吗?

我感觉如果他人问这个问题的话,答复不可变就能够了。上面只是给大家看两个有代表性的例子:

1) String 不可变但不代表援用不能够变

String str = "Hello";
str = str + "World";
System.out.println("str=" + str);

后果:

str=Hello World

解析:

实际上,原来 String 的内容是不变的,只是 str 由原来指向 ”Hello” 的内存地址转为指向 ”Hello World” 的内存地址而已,也就是说多开拓了一块内存区域给 ”Hello World” 字符串。

2) 通过反射是能够批改所谓的“不可变”对象

// 创立字符串 "Hello World",并赋给援用 s
String s = "Hello World";

System.out.println("s =" + s); // Hello World

// 获取 String 类中的 value 字段
Field valueFieldOfString = String.class.getDeclaredField("value");

// 扭转 value 属性的拜访权限
valueFieldOfString.setAccessible(true);

// 获取 s 对象上的 value 属性的值
char[] value = (char[]) valueFieldOfString.get(s);

// 扭转 value 所援用的数组中的第 5 个字符
value[5] = '_';

System.out.println("s =" + s); // Hello_World

后果:

s = Hello World
s = Hello_World

解析:

用反射能够拜访公有成员,而后反射出 String 对象中的 value 属性,进而扭转通过取得的 value 援用扭转数组的构造。然而个别咱们不会这么做,这里只是简略提一下有这个货色。

7. 是否能够继承 String 类

String 类是 final 类,不能够被继承。

8. String str=”i” 与 String str=new String(“i”)一样吗?

不一样,因为内存的调配形式不一样。String str=”i” 的形式,java 虚构机会将其调配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

9. String s = new String(“xyz”); 创立了几个字符串对象

两个对象,一个是动态区的 ”xyz”,一个是用 new 创立在堆上的对象。

String str1 = "hello"; //str1 指向动态区
String str2 = new String("hello");  //str2 指向堆上的对象
String str3 = "hello";
String str4 = new String("hello");
System.out.println(str1.equals(str2)); //true
System.out.println(str2.equals(str4)); //true
System.out.println(str1 == str3); //true
System.out.println(str1 == str2); //false
System.out.println(str2 == str4); //false
System.out.println(str2 == "hello"); //false
str2 = str1;
System.out.println(str2 == "hello"); //true

10. 如何将字符串反转?

应用 StringBuilder 或者 stringBuffer 的 reverse() 办法。

示例代码:

// StringBuffer reverse
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse()); // gfedcba
// StringBuilder reverse
StringBuilder stringBuilder = new StringBuilder();
stringBuilder. append("abcdefg");
System. out. println(stringBuilder. reverse()); // gfedcba

11. 数组有没有 length()办法?String 有没有 length()办法

数组没有 length()办法,有 length 的属性。String 有 length()办法。JavaScript 中,取得字符串的长度是通过 length 属性失去的,这一点容易和 Java 混同。

12. String 类的罕用办法都有那些?

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():宰割字符串,返回一个宰割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。
  • length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比拟。

13. 在应用 HashMap 的时候,用 String 做 key 有什么益处?

HashMap 外部实现是通过 key 的 hashcode 来确定 value 的存储地位,因为字符串是不可变的,所以当创立字符串时,它的 hashcode 被缓存下来,不须要再次计算,所以相比于其余对象更快。

14. String 和 StringBuffer、StringBuilder 的区别是什么?String 为什么是不可变的

可变性

String 类中应用字符数组保留字符串,private final char value[],所以 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% 左右的性能晋升,但却要冒多线程不平安的危险。

对于三者应用的总结

如果要操作大量的数据用 = String

单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

2、Date 相干

3、包装类相干

1. 主动装箱与拆箱

装箱:将根本类型用它们对应的援用类型包装起来;

拆箱:将包装类型转换为根本数据类型;

2. int 和 Integer 有什么区别

Java 是一个近乎纯净的面向对象编程语言,然而为了编程的不便还是引入了根本数据类型,然而为了可能将这些根本数据类型当成对象操作,Java 为每一个根本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是 Integer,从 Java 5 开始引入了主动装箱 / 拆箱机制,使得二者能够互相转换。

Java 为每个原始类型提供了包装类型:

原始类型: boolean,char,byte,short,int,long,float,double

包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

3. Integer a= 127 与 Integer b = 127 相等吗?

对于对象援用类型:== 比拟的是对象的内存地址。
对于根本数据类型:== 比拟的是值。

如果整型字面量的值在 -128 到 127 之间,那么主动装箱时不会 new 新的 Integer 对象,而是间接援用常量池中的 Integer 对象,超过范畴 a1==b1 的后果是 false

public static void main(String[] args) {Integer a = new Integer(3);
    Integer b = 3;  // 将 3 主动装箱成 Integer 类型
    int c = 3;
    System.out.println(a == b); // false 两个援用没有援用同一对象
    System.out.println(a == c); // true a 主动拆箱成 int 类型再和 c 比拟
    System.out.println(b == c); // true

    Integer a1 = 128;
    Integer b1 = 128;
    System.out.println(a1 == b1); // false

    Integer a2 = 127;
    Integer b2 = 127;
    System.out.println(a2 == b2); // true
}

八、常用工具类库

九、单元测试

十、日志

Java 根底知识点总结演绎整顿成题库到此就曾经分享完了,后续可能还会补充~

正文完
 0