华为大佬万字长文总结,梳理的Java入门所有基础知识点,快收藏

今日分享开始啦,请大家多多指教~

1.1 Java 语言概述。

Java 是一种高级编程语言,而且是面向对象的编程语言。Java 语言是美国 Sun 公司(Stanford University Network),在 1995 年推出的高级的编程语言。Java 语言共同创始人之一:詹姆斯·高斯林 (James Gosling),被称为 Java之父。Java 语言的版本:1.0-1.4,5.0…8.0…13.0,本文笔记用的是 jdk 版本为 8.0。

1.2 Java 语言能做什么

Java 语言主要应用在互联网程序的开发领域,网上购物商城、物流、金融、各行各业的门户网站。

1.3 Java 语言的跨平台实现原理

(1) JVM: Java 虚拟机,是专门用来运行 Java 程序的。

(2) 平台:指的就是操作系统,比如 Windows、linux、MacOS 等。

(3) 跨平台: 我们编写的一个 Java 程序,可以做多个操作系统上运行一次编译,到处运行。

(4) 问题思考,如下:

  • Java 程序是跨平台的? ⇒ 正确的 ⇒ 一次编译到处运行。
  • JVM 是跨平台的? ⇒ 错误的 ==> JVM 是实现 Java 程序跨平台的基石。针对不同的操作系统提供不同的 JVM。而程序在 JVM 中运行。
  • Java 程序的跨平台是依靠 JVM 的不跨平台实现的。正确的

1.4 JDK、JRE、JVM 的组成和作用

  • JVM: Java 虚拟机,是专门用来运行 Java 程序的,但是不能单独安装。
  • JRE: Java 运行环境,包含 JVM(Java 虚拟机,是专门用来运行 Java 程序的)和核心类库。
  • JDK: Java 开发工具包,包含 JRE 和开发工具。
  • 三者关系: JDK > JRE > JVM

1.1 Java 语言开发环境搭建

JDK 安装,注意事项:

  • 注意操作系统是 Windows、linux、MacOS
  • 注意操作系统的位数是 32 位还是 64 位
  • 安装 java 相关软件的时候: 安装路径中不允许出现中文和空格(任何开发软件都最好不要安装在中文路径下)

1.2常用 DOS 命令的使用

如何进入DOS 命令操作窗口?

1.开始/命令提示符

2.开始/搜索程序和文件 输入 cmd

3.Windows键 + R –> 输入 cmd

4.窗口空白处/按住 shift 键 + 鼠标右键单击 /在此处开命令窗口

5.常用命令如下表所示:

1.3环境变量 JAVA_HOME 的配置

记事本软件的启动方式?

1.开始/程序/附件/记事本

2.C:/windows/找到notepad.exe命令,双击启动

3.如果在DOS窗口的命令中:

C:\\windows> notepad.exe回车 运行这个命令

首先在C:\\windows路径下,寻找是否存在notepad.exe,发现有,直接运行

D:\\abc> notepad.exe回车 运行这个命令

首先:在 D:\\abc 路径下,寻找是否存在 notepad.exe,发现没有

其次: 如果发现在当前路径 D:\\abc 没有要运行的 notepad.exe 命令,到系统环境变量 path 中寻找

path:… C:\\Windows;…,发现path中配置的路径 C:\\Windows 有该命令,直接运行.

如果path中配置的所有的路径中都没有要运行的命令,运行报错了.

给Java配置环境变量的意义/目的/作用?

让我们可以在任意路径下运行java开发的相关工具(javac: 编译工具,java: 运行工具)

比如jdk的安装路径:C:\\develop\\Java\\jdk1.8.0_162

配置步骤:

1.创建名称为 JAVA_HOME 的环境变量,取值是 C:\\develop\\Java\\jdk1.8.0_162

2.把步骤1中创建的名称为 JAVA_HOME 的环境变量,添加到系统环境变量 path 中

找到系统环境变量path, 在前面添加: %JAVA_HOME%\\bin;…

3.如果在DOS窗口的命令中:

C:\\develop\\Java\\jdk1.8.0_162\\bin> javac.exe回车 运行这个命令

首先在C:\\develop\\Java\\jdk1.8.0_162\\bin路径下,寻找是否存在javac.exe,发现有,

直接运行

D:\\abc> javac.exe回车 运行这个命令 首先:在D:\\abc路径下,寻找是否存在javac.exe,发现没有

其次: 如果发现在当前路径 D:\\abc 没有要运行的 javac.exe 命令,到系统环境变量path中寻找

path:… %JAVA_HOME%\\bin;…, 发现 path 中配置的名称为 JAVA_HOME 的环境变量,对应的路径

C:\\develop\\Java\\jdk1.8.0_162\\bin 中有要运行的 javac.exe 命令,直接运行,

如果 path 中配置的所有路径中,都没有要运行的 javac.exe 命令,运行报错了

寻找名称为JAVA_HOME的环境变量,找到后,使用其配置的具体路径进行替换:

path:… C:\\develop\\Java\\jdk1.8.0_162\\bin;…,

替换后的路径: C:\\develop\\Java\\jdk1.8.0_162\\bin 中有 javac 命令,就可以直接运行

2.1 程序开发的步骤

1. 源程序:

  • 程序员写的程序;
  • 程序员在自己可以看得懂得程序;
  • 程序:字母、数字、其他符号;

源程序是程序员编写的,程序员自己可以看得懂得程序,本质就是一个文本文件,但是扩展名不是 .txt,而是 .java。

2. 生产JVM可以执行的字节码(.class)文件

  • JVM:叫做 Java 虚拟机,是专门用来运行 Java 程序的。但是 JVM 是一个二货,只能识别 0 和 1,而存储 0 和 1 的文件叫做 字节码文件(.class文件)
  • 如何把源文件(程序)翻译成JVM能够执行的字节码文件(程序)呢? 使用 javac 命令(编译命令), 使用格式:javac 文件名.java 例如:编译HelloWorld.java 源文件: javac HelloWorld.java,生成一个字节码文件:HelloWorld.class

3. 把字节码文件交给JVM执行

不管是源文件(程序)还是字节码文件(程序)都存储在硬盘中? 不会自动执行,如何把字节码文件交给 JVM 执行呢? 使用 java 命令(运行命令)。 使用格式: java 文件名 例子:java HelloWorld。

2.2 HelloWorld 案例的编写编译运行

1. 编写源文件。 创建一个名称为 HelloWorld.txt 的文本文件,把扩展名修改为 .java,打开 HelloWorld.java 源文件,输入以下内容,并保存(ctrl+s)。

2. 编译: javac命令。 根据 .java源文件 生产对应的 .class文件(字节码文件)。 使用 javac 命令的格式:javac 文件名.java。javac HelloWorld.java。注意:

  • 保证当前路径下 javac命令 可以使用。
  • 保证当前路径下有要进行编译的 源(.java)文件。
  • 使用编译javac命令时,文件名后面必须写 扩展名.java。

3.运行: java命令。 把 字节码(.class)文件 交给 jvm 执行。使用 java 命令的格式:java 文件名,java HelloWorld,同样要注意:

  • 保证当前路径下 java 命令 可以使用。
  • 保证当前路径下有要进行运行的 字节码(.class)文件。
  • 使用运行 java 命令 时,文件名后面不能写 扩展名.class。

2.3 初学者编写 HelloWorld 常见问题

  • 非法字符问题。Java 中的符号都是英文格式的。
  • 大小写问题。Java 语言对 大小写敏感(区分大小写)。
  • 在系统中显示文件的扩展名,避免出现 HelloWorld.java.txt 文件。
  • 编译命令后的 java文件名需要带文件后缀 .java。
  • 运行命令后的 class文件名(类名) 不带文件 后缀.class。
  • 不要把 main 写成 mian。

2.4 Notepad++ 软件的安装和配置

3.1 注释

概念: 在代码中添加注释可提高代码的可读性。注释中包含了程序的信息,可以帮助程序员更好地阅读和理解程序。在 Java 源程序文件 的任意位置都可以添加注释,且 Java 编译器不编译代码中的注释,也就是说代码中的注释对程序不产生任何影响。所以开发者不仅可以在注释中编写代码的说明文字、设计者的个人信息,还可以使用注释来屏蔽某些不希望执行的代码。

分类: Java 提供了 3 种代码注释,分别为单行注释、多行注释和文档注释。

1、单行注释:// 为单行注释标记,从符号 // 开始直到换行为止的所有内容均作为注释而被编译器忽略。语法格式如下:

// 注释内容

int age ; // 声明int型变量,用于保存年龄信息

2、多行注释: /* */ 为多行注释标记,符号 /* 与 */ 之间的所有内容均为注释内容。注释中的内容可以换行。语法格式如下:

3、文档注释: /**…*/ 为文档注释标记。符号 /** 与 */ 之间的内容均为文档注释内容。当文档注释出现在声明(如类的声明、类的成员变量声明、类的成员方法声明等)之前时,会被 Javadoc 文档工具 读取作为 Javadoc 文档内容。文档注释的格式与多行注释的格式相同。对于初学者而言,文档注释并不是很重要,了解即可。示例如下:

说明:一定要养成良好的编码习惯。软件编码规范中提到 可读性第一,效率第二,所以程序员必须要在程序中添加适量的注释来提高程序的可读性和可维护性。建议程序中的注释总量要占程序代码总量的 20%~50%。

3.2 关键字

引入:邮箱: @前面是用户名,@后面是使用的是哪家的邮箱。

换而言之,关键字是 Java 中已经被赋予特定意义的一些单词,不可以把这些字作为标识符来使用。关键字中的所有字母都是小写的,或者在高级编辑器中彩色显示。

Java中的关键字如下表所示:

3.3 标识符

标识符可以简单地理解为一个名字,用来标识类名、变量名、方法名、数组名等的有效字符序列。Java 规定标识符由 任意顺序的字母、下划线(_)、美元符号($)和数字组成,并且第一个字符不能是数字。标识符不能是 Java 中的保留关键字。 示例:

常见错误:用中文命名标识符是非常不好的编码习惯。当编译环境的字符编码集发生改变后,代码中所有的中文标识符全部会显示成乱码,程序将无法维护。因为 Java 是一种可以跨平台的开发语言,所以发生中文标识符显示成乱码这种情况的概率非常大。编写 Java 代码有一套公认的命名规范:

  • 类名:通常使用名词,第一个单词字母必须大写,后续单词首字母大写。(大驼峰式)
  • 方法名:通常使用动词,第一个单词首字母小写,后续单词首字母大写。(小驼峰式)
  • 变量:第一个单词首字母小写,后续单词首字母大写。(小驼峰式)
  • 常量:所有字母均大写。
  • 单词的拼接:通常使用 userLastName 方式拼接单词,而不是 user_last_name。

4.1 常量的概念和分类

引入:

数学中的常数,对应到 java 中叫常量,数学中的常数有分类,java 中的常量也有分类,而且比数学中的分类更加丰富。

1、概念: 在程序的执行过程中,其值不可以发生改变的量。

2、分类:

  • 整数常量:1314、520
  • 小数常量:13.14、5.20
  • 字符常量:java 中规定字符常量必须使用单引号 \’\’ 引起来,而且单引号 \’\’ 中只能写一个字符(不能不写,也不能写2个以上) 举例:
  • 布尔常量:只有两个值 true 和 false。true:表示肯定的,对的,是的,正确的,成立的。false:表示否定的,错的,不是的,却无的,不成立的。
  • 字符串常量:java 中规定字符串常量必须使用双引号 \”\” 引起来,而且双引号 \”\” 中可以写多个字符(0个、1个、2个…), 举例:
  • 空常量:null

4.2 打印不同类型的常量

同 C语言 一样,Java 程序想要在控制台输出文字,需要调用一个已有的方法,方法如下:

System.out.print(\”Hello!\”); // 此方法输出\”Hello\”后不会自动换行,光标停留同一行的末尾

但与 C语言 不同的是,Java 又提供了一个输出文字后自动换行的方法,这个方法在原有的 print 后面加上了 ln 后缀,方法如下:

System.out.println(\”Hello!\”); // 此方法输出\”Hello\”后会自动换行,光标停留下一行的开头

打印不同类型的常量,示例如下:

4.3 变量和数据类型【重要】

引入:

1、变量概念: 在程序的执行过程中,其值可以在一定范围内发生改变的量。可以把变量理解成为一个 容器,例如一个空烧杯,给变量赋值就相当于给烧杯倒水。如下图所示的那样,变量可以不断更换值,就像烧杯可以反复使用一样:

2、分类:

3、变量定义格式图解分析:

变量的理解:

  • 变量的本质就是内存中的一块空间,空间的大小由数据类型决定。
  • 要想找到变量对应的内存空间的数据,需要给变量对应的内存空间起个名字,叫做变量名称。对于变量的命名并不是任意的。

应遵循以下几条规则:

a.变量名必须是一个有效的标识符。

b.变量名不可以使用 Java 中的关键字。

c.在同一个大括号范围内,变量名不能重复。

d.应选择有意义的单词作为变量名。

说明:在 Java 中允许使用汉字或其他语言文字作为变量名,如 **int 年龄 = 21;** 在程序运行时不会出现错误,但建议尽量不要使用

这些语言文字作为变量名。

  • 变量对应的内存空间中必须有数据才能使用,这种向变量内存空间中,存储数据的过程叫做初始化或者赋值。

图解:

为什么要声明变量呢?简单地说,就是要告诉编译器这个变量属于哪一种数据类型,这样编译器才知道需要分配多少空间给它,以及它可以存放什么样的数据。

4、定义8种变量1:

5、定义8种变量2:

变量的注意事项:定义的变量,不赋值不能使用。定义 long 类型的变量时,需要在整数的后面加 L(大小写均可,建议大写)。同理,定义 float 类型的变量时,需要在小数的后面加 F(大小写均可,建议大写)。

4.4 数据类型转换

类型转换是将一个值从一种数据类型更改为另一种数据类型的过程。例如,可以将 String 类型数据 457 转换为一个数值型,而且可以将任意类型的数据转换为 String 类型。数据类型转换有两种方式,即 隐式转换与显式转换。 如果从低精度数据类型向高精度数据类型转换,则永远不会溢出,并且总是成功的;

而把高精度数据类型向低精度数据类型转换则必然会有信息丢失,甚至有可能失败。这种转换规则就像下图所示的两个场景,高精度相当于一个大水杯,低精度相当于一个小水杯,大水杯可以轻松装下小水杯中所有的水,但小水杯无法装下大水杯中所有的水,装不下的部分必然会溢出。

从低级类型向高级类型的转换,系统将自动执行,程序员无须进行任何操作。这种类型的转换称为 隐式转换,也可以称为自动转换。 下列基本数据类型会涉及数据转换(不包括逻辑类型),这些类型按精度从 “低”到“高” 排列的顺序为 byte < short < int < long < float < double,可对照下图,其中 char 类型比较特殊,它可以与部分 int 型数字兼容,且不会发生精度变化。

隐式转换具体分析如下:

Java 程序中要求参与的计算的数据,必须要保证数据类型的一致性,如果数据类型不一致将发生类型的转换。

int + int

int + long ==> long + long (把int转换成long: 从小到大,自动类型转换,不需要代码的干预)

int + long ==> int + int (把long转成int: 从大到小,强制类型转换,必须手动代码完成)

总结:

1.隐式转换(自动类型转换)概念:

取值范围小的数据或者变量可以直接赋值给取值范围大的变量(小萝卜可以直接放入大坑中)

2.特点:

(1)自动类型转换是自动完成的,不需要代码的干预

(2)byte/short/char类型数据,只要参加运算会自动转换为int类型

(3)byte、short、char–>int–>long–>float–>double

举例:有一个byte类型(1个字节)的数字5: 00000101

byte类型自动类型转换成short类型(2个字节):在左侧补充1个字节的0,因为左侧补充的都是0,对原有数据是没有影响的,仍然是5,

00000000 00000101

byte类型自动类型转换成int类型(4个字节):

在左侧补充3个字节的0,因为左侧补充的都是0,对原有数据是没有影响的,仍然是5

00000000 00000000 00000000 00000101

byte类型自动类型转换成long类型(8个字节):

在左侧补充7个字节的0,因为左侧补充的都是0,对原有数据是没有影响的,仍然是5

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101

总结:根据需求,在数据前面补充若干字节的0,因为补充的都是0,对原有数据大小是没有影响的(打肿脸充胖子)

示例代码,如下:

显式转换具体分析如下:

当把高精度的变量的值赋给低精度的变量时,必须使用显式类型转换(又称强制类型转换),

当执行显式类型转换时可能会导致精度缺失。语法如下:

(类型名) 要转换的值

取值范围大的数据或者变量不能直接赋值给取值范围小的变量(大萝卜不能直接放入小坑中),解决方案:

(1) 把坑变大

(2) 把萝卜变小(强制类型转换)

2.格式:

转后类型 变量名称 = (转后类型) 转前数据或者变量;

long类型(8个字节)的数字5:

long num = 5L;

long类型强制类型转换成int类型(4个字节):

int a = (int)num;//把num中的数据强制类型转换成int类型,并把结果赋值给int变量a

举例: 有一个long类型(8个字节)的数字5:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101

long类型强制类型转换成int类型(4个字节):

砍掉左侧的四个字节的内容,因为砍掉的都是数字0,所以对最终的结果数据没有影响仍然是5

00000000 00000000 00000000 00000101

long类型强制类型转换成short类型(2个字节):

砍掉左侧的六个字节的内容,因为砍掉的都是数字0,所以对最终的结果数据没有影响仍然是5

00000000 00000101

long类型强制类型转换成byte类型(1个字节):

砍掉左侧的七个字节的内容,因为砍掉的都是数字0,所以对最终的结果数据没有影响仍然是5

00000101

总结: 根据需求,砍掉数据左侧的若干字节的数据,只要砍掉的都是0,对原数据没有影响

但是只要砍掉的数据中包含1,就会对原数据产生影响(可能会损失精度)

示例代码2,如下:

图解(其它案例):

4.5 ASCII 码表

计算机是一个二货,只能存储 0和1,所以存储到计算机中的所有内容都会转换成 0和1 进行存储。所以我们在计算机中存储的字符也不例外,也需要把字符转换成 0和1 进行存储,问题: 如何把字符转换成 0和1 呢? 通过 ASCII 编码表: 存储字符和数字对应关系的一张表格。 存储字符时:需要查找 ASCII 码表,找到字符对应的数字,将数字转换为二进制数存放到计算机中。

ASCII 码表如下图所示:

int 类型和 char 类型的运算原理,如下:

计算机中的存储单位(2的10次方就是1024)

务必记住:1个字节是8位

运算符:对常量或者变量进行操作的符号。表达式:用运算符把常量或者变量连接起来符合 java 语法的式子就可以称为表达式。

6.1 算术运算符

Java 中的算术运算符主要有 +(加号)、-(减号)、*(乘号)、/(除号)、%(求余),它们都是二元运算符。Java 中算术运算符的功能及使用方式如下表所示:

其中,“+”和“-” 运算符还可以作为数据的正负符号,如 +5、-7。说明:“+”运算符也有拼接字符串的功能。下面分别演示算术运算符的用法。

【示例1】算术运算符加减乘除。示例代码如下:

6.2 赋值运算符

赋值运算符用符号 “=” 表示,它是一个二元运算符(对两个操作数作处理),其功能是将右方操作数所含的值赋给左方的操作数。例如:

int a = 100; // 该表达式是将100赋值给变量a

/*左方的操作数必须是一个量,而右边的操作数则可以是变量(如a、number)、

常量(如123、\”book\”)、有效的表达式(如45*12)。*/

和其他主流编程语言一样,Java 中也有复合赋值运算符。所谓的复合赋值运算符,就是将赋值运算符与其他运算符合并成一个运算符来使用,从而同时实现两种运算符的效果。Java 中的复合运算符如下表所示:

以“+=”为例,虽然“a += 1”与“a = a + 1”二者最后的计算结果是相同的,但是在不同场景下,两种运算符都有各自的优势和劣势。

【示例2】赋值运算符的使用场景。示例代码如下:

6.3 自增自减运算符

自增、自减运算符是单目运算符,可以放在变量之前,也可以放在变量之后。自增、自减运算符的作用是使变量的值加1或减1。

例如下图所示:

6.4 关系运算符

关系运算符属于二元运算符,用来判断一个操作数与另外一个操作数之间的关系。不管关系表达式多么复杂或者多么简单,返回值一定是布尔类型的结果,要么是 true,要么是 false,如下表所示:

【示例3】关系运算符。示例代码如下:

6.5 逻辑运算符

假定某面包店,在每周二的下午7点至8点和每周六的下午5点至6点,对生日蛋糕商品进行折扣让利活动,那么想参加折扣活动的顾客,就要在时间上满足这样的条件,(周二并且7:00 PM~8:00 PM)或者(周六并且5:00 PM~6:00 PM),这里就用到了逻辑关系。逻辑运算符是对 true(真) 和 false(假) 这两种逻辑值进行运算,运算后的结果仍是一个逻辑值。

用来连接多个条件(布尔表达式的: 结果为true/false的式子),最终的结果也必须是一个布尔类型的数据,要么是true,要么是false

不管逻辑运算符连接的式子有多么简单或者多么复杂,最终结果要么是true,要么是false

分类:

(1) & (shift+7): 逻辑与,表示并且的意思,多个条件同时成立的意思,就是只有多个条件都是true,最终的结果才是true

特点:【有false,则false】: 只要有一个条件不成立(false),结果就是false

(2) |(shift+\\): 逻辑或,表示或者的意思,多个条件,只要有一个成立,最终的结果就是true

特点:【有true,则true】:只要有一个条件是true,结果就是true

(2) !(shift+1): 逻辑取反,!true 就是false,!false 就是true

逻辑运算符的短路效果,如下表所示:

逻辑运算符的运算结果如下表所示:

说明如下:

6.6 位运算符

位运算的操作数类型是整型,可以是有符号的,也可以是无符号的。位运算符可以分为位逻辑运算符和位移运算符两大类。

位逻辑运算符包括 &、|、^和 ~,前三个是双目运算符,第四个是单目运算符。这四个运算符的运算结果如下表所示:

参照上表来看一下这四个运算符的实际运算过程:

1)位逻辑与实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求与,

若两个操作数对象同一位都为1,则结果对应位为1,否则结果中对应位为0。例如,12和8经过位逻辑与运算后得到的结果是8。

0000 0000 0000 1100 (十进制12原码表示)

& 0000 0000 0000 1000 (十进制8原码表示)

0000 0000 0000 1000 (十进制8原码表示)

2)位逻辑或实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求或,

若两个操作数对象同一位都为0,则结果对应位为0,否则结果中对应位为1。例如,4和8经过位逻辑或运算后的结果是12。

0000 0000 0000 0100 (十进制4原码表示)

| 0000 0000 0000 1000 (十进制8原码表示)

0000 0000 0000 1100 (十进制12原码表示)

3)位逻辑异或实际上是将操作数转换成二进制表示方式,然后将两个二进制操作数对象从低位(最右边)到高位对齐,每位求异或,

若两个操作数对象同一位不同时,则结果对应位为1,否则结果中对应位为0。例如,31和22经过位逻辑异或运算后得到的结果是9。

0000 0000 0001 1111 (十进制31原码表示)

^ 0000 0000 0001 0110 (十进制22原码表示)

0000 0000 0000 1001 (十进制9原码表示)

4)取反运算符,实际上是将操作数转换成二进制表示方式,然后将各位二进制位由1变为0,由0变为1。

例如,123取反运算后得到的结果是-124。

~ 0000 0000 0111 1011 (十进制123原码表示)

1111 1111 1000 0100 (十进制-124原码表示)

&、| 和 ^ 也可以用于逻辑运算,运算结果如下表所示:

【示例10】位逻辑运算符的使用场景。示例代码如下:

移位运算有三个,分别是左移 <<、右移>> 和无符号右移 >>>,这三个运算符都属于双目运算符。左移是将一个二进制操作数对象按指定的移动位数向左移,左边(高位端)溢出的位被丢弃,右边(低位端)的空位用0补充。左移相当于乘以2的幂,如下图所示:

例如,short 型整数 9115 的二进制是 0010 0011 1001 1011,左移一位变成 18230,左移两位变成 -29076。

右移是将一个二进制的数按指定的位数向右移动,右边(低位端)溢出的位被丢弃,左边(高位端)用符号位补充,正数的符号位为0,负数的符号为1。右移位运算相当于除以2的幂,如下图所示:

例如 short 型整数 9115 的二进制是 0010 0011 1001 1011,右移一位变成 4557,右移两位变成 2278,运行过程如下图所示:

short 型整数 -32766 的二进制是 0010 0011 1001 1011,右移一位变成 -16383,右移两位变成 -8192,运行过程如下图所示:

无符号右移是将一个二进制的数按指定的位数向右移动,右边(低位端)溢出的位被丢弃,左边(高位端)一律用0填充,运算结果相当于除以2的幂。例如 int 型整数 -32766 的二进制是 1111 1111 1111 1111 1000 0000 0000 0010,右移一位变成 2147467265,右移两位变成 1073733632,运行过程如下图所示:

【示例11】位移运算符的使用场景。示例代码如下:

常见错误:byte、short 类型做 >>> 操作时,可能会发生数据溢出,结果仍为负数。从二进制的实现机制来说,byte 类型和 short 类型不适用于 >>> 操作。

6.7 三元运算符

1.格式:

数据类型 变量名称 = 布尔表达式1 ? 表达式2 : 表达式3;

2.执行流程:

(1)计算布尔表达式1的结果,看是true还是false

(2)如果布尔表达式1的结果为true,就把表达式2的结果赋值给左侧的变量

(3)如果布尔表达式1的结果为false,就把表达式3的结果赋值给左侧的变量

执行流程图解:

【示例13】用三元运算符完成判断一个数字的奇偶性。示例代码如下:

【示例14】使用条件表达式判断一个数是否是3和5的公倍数。示例代码如下:

图解分析:

6.8 圆括号

圆括号可以提升公式中计算过程的优先级,在编程中非常常用。如下图所示,使用圆括号更改运算的优先级,可以得到不同的结果。

圆括号还有调整代码格式,增强阅读性的功能。比如下面的这个公式:

6.9 运算符优先级

Java 中的表达式就是使用运算符连接起来并且符合 Java 规则的式子。运算符的优先级决定了表达式中运算的先后顺序。通常优先级由高到低的顺序依次是:自增和自减运算、算术运算、位运算、逻辑运算、赋值运算。如果两个运算有相同的优先级,会以从左到右的方式进行运算。下表显示 Java 中的运算符的优先级。

今日份分享已结束,请大家多多包涵和指点!

这才是Java基础知识点的总结

前言

本文主要是我之前复习Java基础原理过程中写的Java基础学习总结。Java的知识点其实非常多,并且有些知识点比较难以理解,有时候我们自以为理解了某些内容,其实可能只是停留在表面上,没有理解其底层实现原理。

纸上得来终觉浅,绝知此事要躬行。笔者之前对每部分的内容对做了比较深入的学习以及代码实现,基本上比较全面地讲述了每一个Java基础知识点,当然可能有些遗漏和错误,欢迎读者指正。

这里把重要的面试知识点都写出来了,让大家对知识框架有个基本轮廓。

Java基础学习总结

每部分内容会重点写一些常见知识点,方便复习和记忆,但是并不是全部内容,详细的内容请参见具体的文章地址。

面向对象三大特性

继承:一般类只能单继承,内部类实现多继承,接口可以多继承 封装:访问权限控制public > protected > 包 > private 内部类也是一种封装 多态:编译时多态,体现在向上转型和向下转型,通过引用类型判断调用哪个方法(静态分派)。 运行时多态,体现在同名函数通过不同参数实现多种方法(动态分派)。

基本数据类型

1 基本类型位数,自动装箱,常量池 2 例如byte类型是1byte也就是8位,可以表示的数字是-128到127,因为还有一个0,加起来一共是256,也就是2的八次方。 32位和64位机器的int是4个字节也就是32位,char是1个字节就是8位,float是4个字节,double是8个字节,long是8个字节。 3 基本数据类型的包装类只在数字范围-128到127中用到常量池,会自动拆箱装箱,其余数字范围的包装类则会新建实例

String及包装类

1 String类型是final类型,在堆中分配空间后内存地址不可变。 2 底层是final修饰的char[]数组,数组的内存地址同样不可变。 但实际上可以通过修改char[n] = \’a\’来进行修改,不会改变String实例的内存值,不过在jdk中,用户无法直接获取char[],也没有方法能操作该数组。 所以String类型的不可变实际上也是理论上的不可变。所以我们在分配String对象以后,如果将其 = \”abc\”,那也只是改变了引用的指向,实际上没有改变原来的对象。 3 StringBuffer和StringBuilder底层是可变的char[]数组,继承父类AbstractStringBuilder的各种成员和方法,实际上的操作都是由父类方法来完成的。

final关键字

1 final修饰基本数据类型保证不可变 2 final修饰引用保证引用不能指向别的对象,否则会报错。 3 final修饰类,类的实例分配空间后地址不可变,子类不能重写所有父类方法。因此在cglib动态代理中,不能为一个类的final修饰的函数做代理,因为cglib要将被代理的类设置为父类,然后再生成字节码。 final修饰方法,子类不能重写该方法。

抽象类和接口

1 抽象类可以有方法实现。 抽象类可以有非final成员变量。 抽象方法要用abstract修饰。 抽象类可以有构造方法,但是只能由子类进行实例化。 2 接口可以用extends加多个接口实现多继承。 接口只能有public final类型的成员变量。 接口只能有抽象方法,不能有方法体、 接口不能实例化,但是可以作为引用类型。

代码块和加载顺序

假设该类是第一次进行实例化。那么有如下加载顺序 静态总是比非静态优先,从早到晚的顺序是: 1 静态代码块 和 静态成员变量的顺序根据代码位置前后来决定。 2 代码块和成员变量的顺序也根据代码位置来决定 3 最后才调用构造方法构造方法

包、内部类、外部类

1 Java项目一般从src目录开始有com…A.java这样的目录结构。这就是包结构。所以一般编译后的结构是跟包结构一模一样的,这样的结构保证了import时能找到正确的class引用包访问权限就是指同包下的类可见。 import 一般加上全路径,并且使用.*时只包含当前目录的所有类文件,不包括子目录。 2 外部类只有public和default两种修饰,要么全局可访问,要么包内可访问。 3 内部类可以有全部访问权限,因为它的概念就是一个成员变量,所以访问权限设置与一般的成员变量相同。 非静态内部类是外部类的一个成员变量,只跟外部类的实例有关。 静态内部类是独立于外部类存在的一个类,与外部类实例无关,可以通过外部类.内部类直接获取Class类型。

异常

1 异常体系的最上层是Throwable类 子类有Error和Exception Exception的子类又有RuntimeException和其他具体的可检查异常。 2 Error是jvm完全无法处理的系统错误,只能终止运行。 运行时异常指的是编译正确但运行错误的异常,如数组越界异常,一般是人为失误导致的,这种异常不用try catch,而是需要程序员自己检查。 可检查异常一般是jvm处理不了的一些异常,但是又经常会发生,比如Ioexception,Sqlexception等,是外部实现带来的异常。 3 多线程的异常流程是独立的,互不影响。 大型模块的子模块异常一般需要重新封装成外部异常再次抛出,否则只能看到最外层异常信息,难以进行调试。 日志框架是异常报告的最好帮手,log4j,slf4j中,在工作中必不可少。

泛型

1 Java中的泛型是伪泛型,只在编译期生效,运行期自动进行泛型擦除,将泛型替换为实际上传入的类型。 泛型类用classA { } 2 这样的形式表示,里面的方法和成员变量都可以用T来表示类型。泛型接口也是类似的,不过泛型类实现泛型接口时可以选择注入实际类型或者是继续使用泛型。 3 泛型方法可以自带泛型比如void <E> go(); 泛型可以使用?通配符进行泛化 Object可以接受任何类型 也可以使用 这种方式进行上下边界的限制。

Class类和Object类

1 Java反射的基础是Class类,该类封装所有其他类的类型信息,并且在每个类加载后在堆区生成每个类的一个Class<类名>实例,用于该类的实例化。 2 Java中可以通过多种方式获取Class类型,比如A.class,new A().getClass()方法以及Class.forName(\”com.?.?.A\”)方法。 3 Object是所有类的父类,有着自己的一些私有方法,以及被所有类继承的9大方法。 知乎上有人讨论Object和Class类型谁先加载谁后加载,因为每个类都要继承Object,但是又得先被加载到堆区,事实上,这个问题在JVM初始化时就解决了,没必要多想。

javac和java

1 javac 是编译一个java文件的基本命令,通过不同参数可以完成各种配置,比如导入其他类,指定编译路径等。 2 java是执行一个java文件的基本命令,通过参数配置可以以不同方式执行一个java程序或者是一个jar包。 3 javap是一个class文件的反编译程序,可以获取class文件的反编译结果,甚至是jvm执行程序的每一步代码实现。

反射

1 Java反射包reflection提供对Class,Method,field,constructor1 等信息的封装类型。 2 通过这些api可以轻易获得一个类的各种信息并且可以进行实例化,方法调用等。 类中的private参数可以通过setaccessible方法强制获取。 3 反射的作用可谓是博大精深,JDK动态代理生成代理类的字节码后,首先把这个类通过defineclass定义成一个类,然后用class.for(name)会把该类加载到jvm,之后我们就可以通过,A.class.GetMethod()获取其方法,然后通过invoke调用其方法,在调用这个方法时,实际上会通过被代理类的引用再去调用原方法。

枚举类

1 枚举类继承Enum并且每个枚举类的实例都是唯一的。 2 枚举类可以用于封装一组常量,取值从这组常量中取,比如一周的七天,一年的十二个月。 3 枚举类的底层实现其实是语法糖,每个实例可以被转化成内部类。并且使用静态代码块进行初始化,同时保证内部成员变量不可变。

序列化

1 序列化的类要实现serializable接口 transient修饰符可以保证某个成员变量不被序列化 readObject和writeOject来实现实例的写入和读取。 2 事实上,一些拥有数组变量的类都会把数组设为transient修饰,这样的话不会对整个数组进行序列化,而是利用专门的方法将有数据的数组范围进行序列化,以便节省空间。

动态代理

1 jdk自带的动态代理可以代理一个已经实现接口的类。 2 cglib代理可以代理一个普通的类。 3 动态代理的基本实现原理都是通过字节码框架动态生成字节码,并且在用defineclass加载类后,获取代理类的实例。 一般需要实现一个代理处理器,用来处理被代理类的前置操作和后置操作。在JDK动态代理中,这个类叫做invocationHandler。 4 JDK动态代理首先获取被代理类的方法,并且只获取在接口中声明的方法,生成代理类的字节码后,首先把这个类通过defineclass定义成一个类,然后把该类加载到jvm,之后我们就可以通过,A.class.GetMethod()获取其方法,然后通过invoke调用其方法,在调用这个方法时,实际上会通过被代理类的引用再去调用原方法。 5 而对于cglib动态代理,一般会把被代理类设为代理类的父类,然后获取被代理类中所有非final的方法,通过asm字节码框架生成代理类的字节码,这个代理类很神奇,他会保留原来的方法以及代理后的方法,通过方法数组的形式保存。 cglib的动态代理需要实现一个enhancer和一个interceptor,在interceptor中配置我们需要的代理内容。如果没有配置interceptor,那么代理类会调用被代理类自己的方法,如果配置了interceptor,则会使用代理类修饰过的方法。

多线程

这里先不讲juc包里的多线程类。juc相关内容会在Java并发专题讲解。 1 线程的实现可以通过继承Thread类和实现Runable接口 也可以使用线程池。callable配合future可以实现线程中的数据获取。 2 Java中的线程有7种状态,new runable running blocked waiting timewaiting terminate blocked是线程等待其他线程锁释放。 waiting是wait以后线程无限等待其他线程使用notify唤醒 timewating是有限时间地等待被唤醒,也可能是sleep固定时间。 3 Thread的join是实例方法,比如a.join(b),则说明a线程要等b线程运行完才会运行。 4 o.wait方法会让持有该对象o的线程释放锁并且进入阻塞状态,notify则是持有o锁对象的线程通知其他等待锁的线程获取锁。notify方法并不会释放锁。注意这两个方法都只能在synchronized同步方法或同步块里使用。 5 synchronized方法底层使用系统调用的mutex锁,开销较大,jvm会为每个锁对象维护一个等待队列,让等待该对象锁的线程在这个队列中等待。当线程获取不到锁时则让线程阻塞,而其他检查notify以后则会通知任意一个线程,所以这个锁时非公平锁。 6 Thread.sleep(),Thread.interrupt()等方法都是类方法,表示当前调用该方法的线程的操作。 一个线程实例连续start两次会抛异常,这是因为线程start后会设置标识,如果再次start则判断为错误。

IO流

1 IO流也是Java中比较重要的一块,Java中主要有字节流,字符流,文件等。其中文件也是通过流的方式打开,读取和写入的。 2 IO流的很多接口都使用了装饰者模式,即将原类型通过传入装饰类构造函数的方式,增强原类型,以此获得像带有缓冲区的字节流,或者将字节流封装成字符流等等,其中需要注意的是编码问题,后者打印出来的结果可能是乱码哦。 3 IO流与网络编程息息相关,一个socket接入后,我们可以获取它的输入流和输出流,以获取TCP数据包的内容,并且可以往数据报里写入内容,因为TCP协议也是按照流的方式进行传输的,实际上TCP会将这些数据进行分包处理,并且通过差错检验,超时重传,滑动窗口协议等方式,保证了TCP数据包的高效和可靠传输。

网络编程

承接IO流的内容 1 IO流与网络编程息息相关,一个socket接入后,我们可以获取它的输入流和输出流,以获取TCP数据包的内容,并且可以往数据报里写入内容,因为TCP协议也是按照流的方式进行传输的,实际上TCP会将这些数据进行分包处理,并且通过差错检验,超时重传,滑动窗口协议等方式,保证了TCP数据包的高效和可靠传输。 2 除了使用socket来获取TCP数据包外,还可以使用UDP的DatagramPacket来封装UDP数据包,因为UDP数据包的大小是确定的,所以不是使用流方式处理,而是需要事先定义他的长度,源端口和目标端口等信息。 3 为了方便网络编程,Java提供了一系列类型来支持网络编程的api,比如URL类,InetAddress类等。 后续文章会带来NIO相关的内容,敬请期待。

Java8

1 接口中的默认方法,接口终于可以有方法实现了,使用注解即可标识出默认方法。 2 lambda表达式实现了函数式编程,通过注解可以声明一个函数式接口,该接口中只能有一个方法,这个方法正是使用lambda表达式时会调用到的接口。 3 Option类实现了非空检验 4 各种api的更新,包括chm,hashmap的实现等 5 Stream流概念,实现了集合类的流式访问,可以基于此使用map和reduce并行计算。

我自己是一名从事多年开发的java老程序猿员,目前辞职在做自己的java私人订制课程,今年年初我花了一个月整理了一份最适合2019年学习的java学习干货资料,从最基础的javase到spring各种框架都有整理,送给每一位java小伙伴,想要获取的可以关注我的头条号并在后台私信我:02,即可免费获取。

作者:h2pl

来源:程序员黄小斜

链接:https://url.cn/5GOeFSD

Java基础38个必会知识点,你知道几个?

做Java培训很多年了,也面试过很多Java工程师,总的来说,大家对java基础知识的掌握普遍不大好,如果你觉得自己的技术很强,基础很好,可以划走这篇文章啦~如果你是初学者或者是最近需要面试的同学,可以仔细的看一下这篇文章,小源根据实际项目工作需要,并参考了大厂面试的高频问题,汇总整理了38个必会的基础知识点,送给有需要的同学。

这些知识点呢,是小源精心挑选出来的,对于构建知识体系,我认为是不可或缺的一些点。

第一,面向对象、基础。包括面向对象和面向过程的区别,对象和类的关系,类的特性等等。

第二,网络基础。包括DNS、域名端口、CDNP地址、VPNHTTP和htps get请求和post请求。第三,计算机原理和操作系统。包括内存、CPU、硬盘、Linux基本命令、线程和进程。

第四,数据库基础。关系型数据库和非关系型数据库,索引、慢查询、主从库。

第五,Java开发基础。包括MVC框架、跨域请求、cookie和session正则表达式JVM、JDKJ等等。

剩余的Java知识点,有需要的同学,可以关注小源后厚台dd领取!

本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com

点赞 0
收藏 0

文章为作者独立观点不代本网立场,未经允许不得转载。