目录
Δ前言
- up将JavaSE分为 Java基础 和 Java进阶 两部分——
先说说Java基础,Java基础又被up细分为六大专题:①《面向对象之前需要掌握的知识》;②《面向对象》;③《API—常用类》;④《API—常用工具》;⑤《反射》;⑥《多线程》,无论你是通过什么渠道学习的Java,也无论你学习Java是为了干啥,初学者一定绕不开这六大专题。
再来说说Java进阶,其实Java进阶这个专栏讲得还是JavaSE,主要分为两部分,一个是对常用集合类的源码解读(例如HashMap,LinkedList等),还有一个就是初学者不太可能会用到的知识,例如正则表达式,网络编程,再比如自定义异常,内部类,对象处理流,元注解等知识,前期基本不会用到,等到了做项目、读源码、学框架的时候,诶~,要用到了。- 本篇博文要和大家分享的就是Java基础的第一个专题——《面向对象之前需要掌握的知识》,主要内容包括但不限于JDK的配置和切换、Java数据类型、代码规范、数组等。
- 注意事项——①代码中的注释也很重要;②不要眼高手低,自己跟着过一遍才真正有收获;③点击文章的侧边栏目录或者文章开头的目录可以进行跳转。
- 良工不示人以朴,up所有文章都会适时补充完善。大家如果有问题都可以在评论区进行交流或者私信up。感谢阅读!
一、拾枝杂谈
1.Java是什么?
我们平时说的Java编程语言,无一例外都是指JavaSE(Java Standard Edition),它最开始是由Sun公司的开发团队发明(Sun公司创立于加利福尼亚的斯坦福大学——Stanford University),这个开发团队后来推选了一个人出来作为他们的代表,这个人就是大名鼎鼎的Java之父——James Gosling(詹姆斯·高斯林),也就是说Java之父其实是众多开发人员中的一个代表人物。
后来呢,Sun公司就被Oracle公司收购了。所以,现在Java语言的所有权掌握在Oracle公司手里,我们在后面的学习中还会经常见到这个公司的名字。
那java语言有什么特点呢?
1)面向对象(Object Oriented Programming,即OOP)。
2)健壮,Java是强类型机制的语言(对比JavaScript是弱类型机制的语言),且Java提供了“异常处理”,“垃圾回收”等机制。
3)跨平台性(原因我们下面马上会是说到)。
4)半编译型半解释型语言,或者说,Java既具有编译型语言的特征,也具有解释型语言的特征。(具体内容up会在计组里说到)
2.计组前瞻:
- up之后会出“计算机组成原理”相关的博文,作为计算机基础四大件——“计算机学科专业基础”(即408中)的关键一环,计组是每个学编程的人都逃不掉的。
- 这里先简单给大家提一嘴,计算机主要由Hardware(硬件)和Software(软件)两大部分组成——
- 概念:
Hardware:指计算机中由电子、机械和光电元件等组成的各种物理装置的总称。
Software:指按照特定顺序组织的计算机数据和指令的集合。
- 组成:
Hardware:根据经典的“冯·诺依曼”体系结构,硬件有五大组成部分,分别是——①运算器;②控制器;③存储器;④输入设备;⑤输出设备(其中,前两者为CPU的主要构成)。
Software:主要分为“系统软件”和“应用软件”两大类。系统软件比如黑窗口DOS,以及操作系统像是Windows,Linux,Unix,Mac,Android等;应用软件就是我们平时称的那个“软件”了,比如百度网盘,淘宝,Google浏览器等等。
3.JDK,JRE,JVM?
1. JDK:
Java Development Kit,即Java开发工具包,用于开发Java程序。
JDK = JRE + java的开发工具,其中,Java的开发工具包括 Java 编译器(javac)、Java 文档生成器(javadoc)、Java 反汇编器(javap)等等,我们在后面的学习中会经常用到这些开发工具。
特别说明:
①一般我们说的“诶,你Java用的哪个版本?”,说的都是JDK的版本,目前主流版本有JDK8.0和JDK17.0两个版本。
②Java程序开发和运行原理——示意图如下:
编辑
2. JRE:
Java Runtime Environment,即Java运行环境,包含运行Java程序需要的组件,用于运行Java程序。
JRE = JVM + Java的核心类库,其中,Java核心类库包括java.base模块(最基础最重要的模块),java.sql模块,java.net.http模块等等。
3. JVM:
Java Virtual Machine,即Java虚拟机。
JVM负责将Java程序翻成机器语言,交给低层操作系统执行,并保证运行效果;JVM可以实现Java程序的跨平台性,但JVM本身并不能跨平台。(关于JVM,up之后会专门出一个专栏讲解,就放在《Java高级》专栏中。)
Java的跨平台性,是由于通过javac命令编译成的字节码文件,可以在多个系统下运行。
二、环境搭建
1.JDK安装和配置:
1.1 人话
上文我们说了,Java的版本就是指JDK的版本,这么看来JDK选择哪个版本对我们使用Java影响很大,因为不同版本的JDK,其核心类库,以及语言特性,都有不同程度的出入。
目前主流的版本是JDK8.0 和 JDK17.0,这两个版本都是长期支持版,也是用的最多的两个版本,我的建议是两个版本你都下载上,但是主要用JDK17.0(可以随意切换JDK版本,下文会有演示)。
不过我想不会有人无聊到来Java基础教程里找JDK的下载安装教程,你应该直接去找“JDK下载安装教程”;因此,下载和安装自己想办法,up这里只给出JDK的配置教程,以及当安装了多个JDK版本后,如何切换当前使用的JDK版本。
1.2 JDK的配置
第一步,首先,右键点击我的电脑,选择属性,如下图所示:
编辑
第二步,接着,在出现的设置页面上,右侧选择高级系统设置,如下图所示:
编辑
第三步,接着,在出现的子菜单设置页面中,选择环境变量,如下图所示:
编辑
第四步,增加一条"JAVA_HOME"环境变量,选择到JDK安装目录的下一级即可(JDK所在的文件夹点进去那一级),如下图所示:
编辑
第五步,也是最后一步,配置Path变量,具体操作如下图所示:
编辑
选择编辑"Path"变量,然后在Path变量中增加一条环境变量,目录要选择到JDK的目录里面的bin目录的下一级(亦可用图中所示下面那种方式,即%JAVA_HOME%\bin,默认指向当前JAVA_HOME路径所属的JDK的bin目录下,一个道理),如下图所示:
编辑
然后点击“确定”,就完事儿了。
1.3 如何切换JDK的版本?
同时安装了两个JDK版本,如何配置环境变量以达到切换JDK版本的效果?
eg : 当前使用的JDK版本是Java8,如下图所示 :
编辑
我们在cmd命令窗口下输入“java -version”命令也可以查看当前设备的JDK版本,如下图所示 :
编辑
可知当前设备的JDK版本是JDK8.0,现在up要将其切换到JDK17.0。
首先,将JAVA_HOME环境变量更改为JDK17.0所在的目录,如下图所示 :
编辑
然后,配置path环境变量,将配置的JDK17.0的path环境变量上移到JDK8.0的path环境变量之上(那个%JAVA_HOME%\bin就是JDK8.0关联的环境变量),如下图所示 :
编辑
此时,若我们再次到cmd命令窗口下输入“java -version”命令(注意——需要重新打开一个cmd窗口),会发现JDK版本已经切换到了JDK17.0,如下图所示 :
编辑
PS:如果想了解在IDEA中怎么切换当前项目使用的JDK版本,可以移步“Spring IOC—基于注解控制和管理Bean”一文,直接看“@Resource自动装配”那里。
2.DOS的简单使用:
2.1 介绍
DOS:Disk Operating System磁盘操作系统。DOS原理图如下所示:
编辑
2.2 常用的dos命令及演示
1> dir / (dir + 路径):查看 当前目录 / 指定目录 有什么内容。
2> cd /D c: 切换到C盘下,亦可选择切换到其他盘下(例如:cd /D d:切换到D盘下)。
3> cd..:切换到上一级。【PS:cd = change directory】
4> cd\:切换到根目录。
5> tree / (tree + 路径):查看 当前目录 / 指定目录 下的所有子级目录。
6> cls:清屏。
7> exit:退出DOS。
8> echo xxx > yyy.txt:输入xxx内容到yyy文本文件中,如果yyy文件不存在就创建它;如果yyy文件存在就用xxx内容覆盖它原有的内容。
9> type nul > xxx.txt:创建一个空内容的名字叫xxx的文本文件。
很简单,这里up只演示第一个(其他真懒得演示了😘),其他的大家自己动手去试试就学会了。
比方说,up现在在D盘的用户目录下,如下图所示:
编辑
up通过在该目录路径栏输入“cmd”从当前目录进入DOS,并通过dir 和 dir documents命令,分别 从查看当前目录下和当前目录下的“文档”目录下都有什么文件,演示GIF图如下所示:
编辑
2.3 通过cmd命令运行Java程序演示:
首先我们在桌面创建一个Test.java源文件,如下图所示:
编辑
Test.java代码如下:
class Test { public static void main(String[] args) { System.out.println("This is only a temporary tentitive file~"); } }
现在,我们要在DOS下完成两件事——①利用javac命令工具对Test.java编译,生成Test.class文件;②利用java命令工具运行Test.class。
先来干第一件事,如下GIF图所示:
编辑
可以看到,Test.java成功被编译,并在桌面上(当前目录)自动生成了Test.class字节码文件。
再来干第二件事,如下GIF图所示:
编辑
可以看到,Test.class被正确执行,并且成功打印出了"This is only a temporary tentitive file~"。
特别注意一点——在DOS下用cmd使用java命令工具时,例如上面演示up用的“java Test”,类名后面不能加.class,否则会被误认为是类名的一部分,造成运行错误,如下图所示:
编辑
3.IDEA的详细使用教程:
3.1 什么是IDE?
IDE,全称Integrated Development Environment,即“集成开发环境”,是指整合了代码的编写、运行、分析、调试等一系列功能的开发软件;确切地说,它是一个为开发者提供综合工具集的平台,核心目标是简化开发流程,将编写、调试、测试和部署代码的工具集成到一个统一的界面中。
3.2 什么是IDEA?
目前主流的运行Java程序的IDE有两个——①IDEA;②Eclipse。前者智能程度高、功能全面;后者免费。
大多数Java程序员使用的IDE,包括企业员工,都是IDEA,因为好用,Eclipse更可能是学校用(比如考研复试里面有机试的时候)。那IDEA呢,是由Jet Brains公司开发的(在捷克首都),卖得还挺贵,咳咳,但是我们一般是用那啥版本的。
3.3 IDEA入门指南:
具体见这篇博文——链接如下:
“IDEA详细入门指南”一文,主要内容包括 :
① 项目和类的创建
② 如何运行一个程序
③ IDEA中包的使用
④ IDEA中常用的20个快捷键⑤ IDEA中语句模板的使用
三、语法特性
1.代码规范:
1)类、方法的注释要以javadoc的方式来写;注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档。
2)非javadoc的注释,往往是给代码的维护者看的,着重告诉读者为什么这样写,如何修改,注意什么问题等。
3)代码排版缩进时,先选中要排版的代码,再用Tab 或 Shift Tab进行缩进。
4)源文件要使用UTF-8编码。
5)行宽度不要超过80个字符。
6)代码编写风格——选择次行风格 或 行尾风格(IDEA默认风格)
PS:常见javadoc注释符如下表所示:
| 标签 | 描述 | 示例 |
@author |
标识一个类的作者 | @author John Doe |
@deprecated |
指名一个过期的类或成员 | @deprecated This method is no longer supported. |
{@docRoot} |
指明当前文档根目录的路径 | {@docRoot}/images/logo.png |
@exception |
标志一个类抛出的异常 | @exception IOException On input error. |
{@inheritDoc} |
从直接父类继承的注释 | {@inheritDoc} |
{@link} |
插入一个到另一个主题的链接 | {@link java.util.List} |
{@linkplain} |
插入一个到另一个主题的链接,但该链接显示纯文本字体 | {@linkplain java.util.List List} |
@param |
说明一个方法的参数 | @param username The name of the user. |
@return |
说明返回值类型 | @return The number of users. |
@see |
指定一个到另一个主题的链接 | @see java.util.Collections |
@serial |
说明一个序列化属性 | @serial description |
@serialData |
说明通过 writeObject() 和 writeExternal() 方法写的数据 |
@serialData description |
@serialField |
说明一个 ObjectStreamField 组件 |
@serialField name type description |
@since |
标记当引入一个特定的变化时 | @since 1.5 |
@throws |
和 @exception 标签一样,标志一个类抛出的异常 |
@throws IOException On input error. |
{@value} |
显示常量的值,该常量必须是 static 属性 |
{@value java.lang.Math#PI} |
@version |
指定类的版本 | @version 1.0 |
2.常量、变量、数据类型:
2.1 常量
- 概念:是指在程序执行的过程中,其值不可以发生改变的量。
- 分类:大体上分为两大类——“字面值常量” 和 “自定义常量”。其中,字面值常量是指直接写在代码中的固定值,它又可分为六种:①字符串常量,如"HELLO WORLD";②整数常量,如11,-23;③小数常量,如2.333;④字符常量,如'R', 'A', '9';⑤布尔常量,如true,false;⑥空常量,即null。而自定义常量,则是由final修饰的变量,通过final关键字来定义。
- 补充:在Java中,整型常量默认是int类型,声明long类型常量必须在后面加“l” 或 “L”。
ConstantDemo类代码如下:
package csdn.foundation.before_info.initial; public class ConstantDemo { /** * 补充两个快捷方式: * ①main方法的快捷键:psvm(public static void main(String[] args){} * ②输出语句的快捷键:sout(System.out.println();) */ /* 常量: 在程序的运行过程中,其值不会改变的量。 字面值常量分类: Ⅰ字符串常量:要用双引号括起来。eg:“abc” Ⅱ字符常量: 要用单引号括起来。eg:‘A’,'0' Ⅲ整数常量:11,23 Ⅳ小数常量:11.23 Ⅴ布尔常量:值只有两个,true 和 false Ⅵ空常量:NULL(null) */ public static void main(String[] args) { //演示: //Ⅰ字符串常量: System.out.println("abc"); System.out.println("123");//此时的123是一个字符串常量。 //Ⅱ字符常量: System.out.println('A'); System.out.println('0'); //Ⅲ整数常量: System.out.println(11); System.out.println(23); //Ⅳ小数常量: System.out.println(8.24); //注意整数常量和小数常量直接在括号里写就行。 //Ⅴ布尔常量: System.out.println(true); System.out.println(false); } }
运行结果:
编辑
2.2 变量
- 变量三要素:①数据类型;②变量名;③变量初始值。
- 变量的定义:数据类型 变量名 = 初始值。
- 补充:在Java中,局部变量在定义时必须初始化(如果局部变量未被使用,则可以不初始化),而成员变量则有自己的默认值。
VariableDemo类代码如下:
package csdn.foundation.before_info.initial; public class VariableDemo { public static void main(String[] args) { //定义变量,记录学生个数。 //变量的定义格式: 数据类型 变量名 = 初始化值。 int stu_number = 12; System.out.println(stu_number);//输出语句此处直接写变量名即可。 } }
运行结果:
编辑
2.3 数据类型
- 分类:基本数据类型 和 引用数据类型。
- 基本数据类型分类:①整数型:byte, short, int, long;②浮点型:float(单精度), double(双精度);[整数型和浮点型又可统称为数值类数据类型] ③字符型:char;④布尔型:即布尔类型boolean。Java中一共有八种基本数据类型。
- 引用数据类型分类:①类(class)[String就属于这块儿];②接口(interface);③数组。Java中一共有三种引用数据类型。
- 八种 基本数据类型,如下表所示:
编辑 PS1:对于boolean类型,不可以用0 或 非0来代替false 和 true(与C语言不同),即boolean类型的取值范围只能是true 和 false。
PS2:浮点数尽量用 double 类型存储,而不是 float。
DataTypesDemo类代码如下:
package csdn.foundation.before_info.initial; /* 变量的定义形式: 数据类型 变量名 = 初始化值; 八种基本数据类型: byte,short,int,long,float,double,char,boolean 定义变量的注意事项: 1.整形默认是int类型,定义long类型变量的时候,后边要加字母l(L) 2.浮点型默认是double类型,定义float类型变量的时候,后边要加字母f(F) !!!使用变量的注意事项: 1.变量未赋值,不能使用(局部变量)。 2.变量只在它所属的范围内有效(即变量的作用域) 3.一行上可以定义多个变量,但是不建议这样写。 */ public class DataTypesDemo { public static void main(String[] args) { //byte类型的变量 byte b = 11; System.out.println(b); //short类型的变量 short s = 4; System.out.println(s); //int类型的变量 int i = 24; System.out.println(i); //long类型的变量 long l = 10000L; System.out.println(l); //float类型的变量 float f = 11.23F; System.out.println(f); //double类型的变量 double d = 66.6; System.out.println(d); //char类型的变量 char ch = 'K'; System.out.println(ch); //boolean类型的变量 boolean b1 = true; boolean b2 = false; System.out.println(b1); System.out.println(b2); System.out.println("--------------------------------"); int a; a = 11; System.out.println(a); //代码块:大括号括起来的内容就是代码块。 { int aa = 20; System.out.println(aa); }//变量只在它所属的代码块内有效。方法与代码块之间空一行。 } }
运行结果:
编辑
2.4 数据类型转换
- 分类:①自动(隐式)类型转换:“小类型 → 大类型”,自动提升为大类型,运算结果也是大类型。②强制(显式)类型转换:手动将大类型转换成小类型,运算结果是小类型;转换格式——“小类型 变量名 = (小类型) 大类型数据;”。
- 注意事项:当且仅当大类型数据可以转换为小类型数据时,才能进行强制类型转换,否则会造成精度丢失。
- 补充:
- int 转 float 虽然是小类型转大类型,但可能丢失精度,因为根据IEEE754标准, float 的尾数部分只有 24 位有效位(含1位隐藏位),而 int 需要 32 位表示。如果需要更高的精度,可以使用 double 类型(64 位浮点数,尾数部分有 53 位有效位),但即便如此,double 也无法精确表示所有 long 类型的值。PS:具体细节up将在《计算机组成原理》专栏详细解释。
- byte,short 和 char之间 不会发生 相互自动转换。
- byte, short, char参与运算时,结果自动转换为int类型。
- 当把数值类变量赋值给byte时,先判断该数是否在byte范围内,是就可以赋值。
- 在Java中,boolean类型不参与数据类型转换。
- “表达式” 结果的类型自动提升为所操作的数据中最大的类型。
ConversionDemo类代码如下:
package csdn.foundation.before_info.initial;/* 类型转换: 1) 隐式类型转换: "小 ---> 大" 数据类型的范围从小到大如下: byte,short,char -> int(默认的整形) -> long -> float -> double(默认的浮点型) Boolean类型不参与比较,它的值只有true和false两个。 2) 强制类型转换: "大 ---> 小" 目标类型 变量名 = (目标类型) 要转换的值 注意: 强制类型转换在使用的时候可能会出现丢失精度的问题 */ public class ConversionDemo { public static void main(String[] args) { //定义两个int类型的变量 int a = 10; int b = 11; System.out.println(a + b); //我可以把a+b的结果接收一下。 int c = a + b; System.out.println(c); System.out.println("_____________________________ "); //定义一个int类型的数据 和 一个byte类型的数据 int aa = 10; byte bb = 20; System.out.println(aa + bb); /**byte cc = aa + bb;//会报错!!,因为byte类型和int类型计算,会先将byte类型提升为int类型再计算,结果也是int类型。*/ int cc = aa + bb;//即:隐式类型转换。 System.out.println(cc); System.out.println("______________________________"); //思考:如何使用byte类型的变量来接收aa + bb? byte dd = (byte) (aa + bb); System.out.println(dd); //答: 强制类型转换. System.out.println("______________________________"); double d1 = 3.14; int a1 = (int) d1;//此条代码的意义是:将double类型的结果值强制类型转换为整数. System.out.println(a1); } }
运行结果:
编辑
3.标识符:
3.1 简介
- 标识符定义:给类、方法、变量、常量等起名字的字符序列,就是标识符
- 标识符的组成部分:英文大小写字母、数字、下划线_ 和 美元符号$
3.2 定义规则
- 不能以数字开头
- 不能是关键字 和 保留字(但可以包含)
- 严格区分大小写
PS_1 :常用关键字如下——
1)用于定义数据类型的关键字:
| 关键字 | 描述 |
| class | 定义类 |
| interface | 定义接口 |
| enum | 定义枚举类型 |
| @interface | 定义注解类型 |
| byte | 字节类型 |
| short | 短整型 |
| int | 整型 |
| long | 长整型 |
| char | 字符类型 |
| float | 单精度浮点型 |
| double | 双精度浮点型 |
| boolean | 布尔类型 |
| void | 无返回值类型 |
| true | 布尔值真 |
| false | 布尔值假 |
| null | 空引用 |
2)用于定义流程控制的关键字:
| 关键字 | 描述 |
| if | 条件判断 |
| else | 条件分支 |
| switch | 多分支选择 |
| case | switch 分支 |
| default | switch 默认分支 |
| for | 循环 |
| while | 循环 |
| do | 循环(do-while循环) |
| break | 跳出循环或 switch |
| continue | 继续下一次循环 |
| return | 返回值 |
3)用于定义访问权限修饰符的关键字:
| 关键字 | 描述 |
| public | 公共访问权限 |
| protected | 受保护的访问权限 |
| private | 私有访问权限 |
4)用于定义类、函数、变量修饰符的关键字:
| 关键字 | 描述 |
| abstract | 抽象类或方法 |
| final | 不可继承或不可修改 |
| static | 静态成员 |
| synchronized | 同步方法或代码块 |
5)用于定义类与类之间关系的关键字:
| 关键字 | 描述 |
| extends | 继承类 |
| implements | 实现接口 |
6)用于定义建立实例、引用实例、判断实例的关键字:
| 关键字 | 描述 |
| new | 创建实例 |
| this | 当前对象引用 |
| super | 父类对象引用 |
| instanceof | 判断对象类型 |
7)用于处理异常的关键字:
| 关键字 | 描述 |
| try | 尝试执行代码块 |
| catch | 捕获异常 |
| finally | 最终执行代码块 |
| throw | 抛出异常 |
| throws | 声明可能抛出的异常 |
8)用于包的关键字:
| 关键字 | 描述 |
| package | 定义包 |
| import | 导入包 |
9)其它关键字:
| 关键字 | 描述 |
| native | 本地方法 |
| strictfp | 严格浮点计算 |
| transient | 非序列化字段 |
| volatile | 易变字段 |
| assert | 断言 |
10)自己命名时要避免使用的保留字:
| 保留字 | 描述 |
byValue |
目前未使用,可能用于未来的语言特性。 |
cast |
目前未使用,可能与类型转换相关。 |
future |
目前未使用,可能用于未来的语言特性。 |
generic |
目前未使用,可能与泛型相关。 |
inner |
目前未使用,可能与内部类相关。 |
operator |
目前未使用,可能与操作符重载相关。 |
outer |
目前未使用,可能与外部类相关。 |
test |
目前未使用,可能与测试相关。 |
var |
从 Java 10 开始,var 被用作局部变量类型推断的关键字,但在早期版本中是保留字。 |
goto |
保留字,但 Java 中未实现 goto 语句(为了避免代码混乱)。 |
const |
保留字,但 Java 中使用 final 代替 const 来定义常量。 |
3.3 命名规范
- 类和接口:首字母大写,如果有多个单词,每个单词首字母大写(大驼峰),eg:HashMap,OutputStreamWriter。
- 变量和方法:首字母小写,如果有多个单词,从第二个单词开始首字母大写(小驼峰),eg:getName,toString。
- 自定义常量:所有字母全部大写,多个单词之间用下划线(_)隔开,eg:MAX_SIZE,MIN_VALUE。
- 包名:全部小写,如果有多级包,则包名之间用点号(.)隔开,遵循域名反写的格式:com.cyan.pot。
- 总结:驼峰命名,见名知意。
4.运算符:
4.1 常见运算符及它们的优先级
单目运算符 > 算术运算符 > 位运算符(特指位移运算符) > 关系运算符 > 位运算符(指除了位移运算符之外的位运算符) > 逻辑运算符 > 三目运算符 > 赋值运算符
4.2 单目运算符
- 分类:++(自增),--(自减),!(逻辑非),~(按位取反)
- PS:偶数个逻辑非(!)不改变真值的结果,eg:(!!true) == true,(!!!!false) == false。
4.3 算术运算符
- 分类:+(加),-(减),*(乘),/(除),%(取模)
- 加法运算的特点:
① 加法两边是数值型数据时,进行加法运算;
② 加法两边出现字符型数据参与运算时(eg:'a', 'o'等字符),用该字符在计算机中所表示的数值进行运算。(byte, short, char参与运算时,结果自动转换为int类型)
③ 加号两边有任意一边是字符串时,进行字符串的拼接操作。- PS:华氏温度转摄氏温度的公式:摄氏温度 = (5 / 9) * (华氏温度 - 100)。
4.4 位运算符(特指位移运算符)
<<(算术左移),>>(算术右移),>>>(逻辑右移)
4.5 关系运算符
- 定义:关系运算符是用来描述两个变量值之间的关系的。
- 分类:>(大于),<(小于),>=(大于等于),<=(小于等于),==(等于),!=(不等于)。
4.6 位运算符(指除了位移运算符之外的位运算符)
① &:按位与,注意与&&(短路与)作区分。当进行位运算时,&表示把左右两个数的二进制代码的每一位都进行”与“操作,算出组成的新的二进制代码所对应的数。&还可以作为信息的采集方式,比如 通过 “a & 0101”,就能判断出a的第一位和第三位。
② |:按位或,注意与||(短路或)作区分。
③^:按位异或(不允许相同):相同为0,不同为1。
4.7 逻辑运算符
- 使用:逻辑运算符两端一般连接值为布尔类型的关系表达式。
- 分类:&(逻辑与),|(逻辑或),&&(短路与),||(短路或)。特别注意——当& 或 | 两边不是booloean类型时,表示位运算。
- 逻辑与& 和 短路与&& 的区别——
短路与&&:如果第一个条件为false,则第二个条件不会进行判断,最终结果直接为false,效率高。
逻辑与&:不管第一个条件是否为false,第二个条件都要进行判断,效率低。- 逻辑或| 和 短路或|| 的区别——同理。
4.8 三目运算符 / 三元运算符
a ? b : c —— 如果 a 成立,就执行b,否则执行c。
4.9 赋值运算符
- 分类:①基本赋值运算符:=;②扩展赋值运算符(复合赋值运算符):+=,-=,/=,*=,%=。
- 扩展赋值运算符的好处:省略了强制类型转化。
short s = 1; //s = s + 1; //(报错: 不能把int类型赋值给short类型) s += 1; //没事儿,相当于s = (short) (s + 1);
5.Scanner类的简单使用:
5.1 概念
扫描器,即可以通过Scanner类扫描用户在控制台录入的数据。
5.2 代码演示
ScannerDemo类代码如下:
package csdn.foundation.before_info.scanner.extendclass; // 1.导包 import java.util.Scanner; public class ScannerDemo { public static void main(String[] args) { // 2.创建Scanner类的对象 // System.in:标准的输入流,默认指向键盘。(编译类型为InputStream) boolean key = true; Scanner sc = new Scanner(System.in); //根据Scanner类的构造方法,需要传入一个指定输入流。 // 3.接收数据 System.out.println("请输入一个实数:"); //为了防止InputMismatchException异常,需要先对f进行判断 loop: while (key) { if (sc.hasNextFloat()) { float f = sc.nextFloat(); sc.nextLine(); //nextLine用于“消化”掉Enter键的'/n'换行符 System.out.println("f:" + f); key = false; } else break loop; } //接收字符串类型的数据 System.out.println("请输入一个字符串:"); //方法一: String s = sc.nextLine(); //结束标志:回车 System.out.println("s:"+ s); //方法二: /*String s = sc.next(); //结束标志:空白符(回车,Tab键,空格) eg:空格后的字符都不会计入 System.out.println("s:"+ s);*/ // 4. 关闭扫描器 sc.close(); } }
运行结果如下GIF图所示:
编辑
6.Random类的简单使用:
6.1 概念
随机数,用于产生随机数的类。
6.2 代码演示
RandomDemoEX类代码如下:
package csdn.foundation.before_info.Random; /** 猜数字的小游戏,系统产生一个1~100之间的随机数,请猜出这个数是多少。 */ import java.util.Random; import java.util.Scanner; //记得导包 public class RandomDemoEX { public static void main(String[] args) { //1.获取一个1~100之间的随机数,让用户猜。 Random r = new Random(); Scanner sc = new Scanner(System.in); int num = r.nextInt(100) + 1; /* "0~100前闭后开区间" + 1, 就能取到100. 即[1,101) r.nextInt(99) --> [0,99) */ for ( ; ; ) { //2.通过键盘录入获取用户猜的数字,并接收。 System.out.println("请猜一下1~100间的这个整数是多少:"); int t = sc.nextInt(); //3.比较两个数字大小,看是否一致,并给予提示。 if (t < num) System.out.println("猜小了,哥们"); else if (t > num) System.out.println("猜大了,哥们"); else { System.out.println("恭喜哥们,可算混对了!"); break; } }//4.因为不知道你啥时候猜对,所以用死循环。 sc.close(); } } //PS:猜数字技巧:折半法。
运行结果:(如下GIF图)
编辑
四、流程控制
1.顺序结构:
- Java中定义变量时应采用合法的前向引用(即先定义后使用)。
- 写程序的时候,做数据测试应该测试以下几种情况——
① 正确数据。
② 错误数据。
③ 边界数据。- 读程序的时候,应该遵循以下步骤——
① 程序的整体执行流程。
② 每条语句的具体含义。
③ 试数(代入一个数据过一遍)。
2.选择结构:
- 在用法上,选择结构与C语言类似。
- 在Java中,switch (表达式) ,表达式的取值类型可以是①byte; ②short; ③int; ④char;
JDK5开始,还可以是 ⑤枚举;
JDK7开始,还可以是 ⑥String。
PS:对于switch语句,表达式的数据类型应和case后的常量类型一致,或者是“可以自动转换成的能够相互比较的类型”,eg:表达式是char类型,而case后常量的类型是int类型。- 多分支 if条件语句 可以没有 单else语句。
- 建议实际开发中,分支语句的嵌套不要超过三层。
- switch分支 和 if分支,应该用谁?
若需要判断的是具体数值且值的数目不多(离散的值),而且值的类型符合switch表达式的六种类型,更推荐用switch分支。
若要对一个或多个连续的区间进行判断,更推荐if分支,
3.循环结构:
- for循环语句的格式:
for (初始条件语句; 判断条件语句; 控制语句) { //循环体——重复执行的代码 }
- ①初始条件语句——用于循环变量的初始化。用一个Java的赋值语句来完成,eg: int i = 1; PS:for循环中,初始条件语句可以有多条语句,但要求变量的数据类型相同,多条初始语句之间用逗号隔开。
②判断条件语句——判断本次循环是否执行,往往优先采用"<"(小于号),返回一个布尔值。
③控制语句——用于控制循环执行的次数 或 循环的执行特性。PS:控制语句也可以有多条,中间照样用逗号隔开。- while 循环:相比于for循环,初始条件语句 和 控制语句可以省略。
- do-while循环:要点与C语言相同,do-while循环至少执行一次,记得最后的while()后要加;(分号)。
- for循环 和 while循环,应该用哪个?
一般来说,for循环和while循环可以互相改写,但while循环格式更加简洁;for循环更倾向于循环次数是固定的,而while循环更倾向于循环次数不固定的情况。- 死循环:代码如下:
//1. for循环版本的死循环 for ( ; ; ) { //循环体,根据实际需求给出结束循环的条件。 } //2. while循环版本的死循环 while (true) { //循环体,根据实际需求给出结束循环的条件。 }
演示一下循环结构,Orange类代码如下:
package csdn.foundation.before_info.control; /** * 1024程序员节,给可爱的程序员发橙子, * 已知条件: * 1.假设有三个班级,每个班级有十五位码农,现在要将100个橙子分别发给每位码农,且每人只能拿一个橙子。 * 2.假设编号中有5的哥们不吃橙子 * 3.如果当前编号的码农已经有了橙子,则不再给该码农发放橙子,若橙子发完了,则活动结束。 */ public class Orange { public static void main(String[] args) { int count = 0; //count变量用于记录已经发放的橘子的个数。 firstFor: //带标号的循环 for (int i = 1; i <= 3; i++) { secondFor: for (int j = 1; j <= 15; j++) { if (j % 10 == 5 || j / 10 % 10 == 5) { continue secondFor; //跳过当前码农,直接进行下一次循环(内层循环) } System.out.println("正在给第"+ i +"个班的第" + j + "个哥们发橘子" + ",哥们吃的挺香"); count++; if (count >= 100) break firstFor; } System.out.println(); } System.out.println("总共发放了"+ count +"个橘子"); } }
运行结果:
编辑
五、方法
1.概念:
也叫"函数",是完成特定功能的代码块。
2.格式:
修饰符 返回值类型 方法名(形参列表) {
//方法体语句;
return 返回值; // Java中,方法的返回值必须和函数名前等等返回值类型相同。
}
注意事项——
① 参数类型可以是基本类型,也可以是引用类型 。
② 方法必须定义在类中,方法之间 是平级关系,方法不能嵌套定义。
③ 当方法的返回值类型为void时,return语句可以省略。
3.方法重载:
- 定义:同一个类中的多个方法,方法名相同但形参列表不同,这样的情况称为”方法重载“。对于重载的多个方法,可以通过方法签名(方法名 + 形参列表)准确地找到具体方法。
- 为什么需要方法重载?
当实现的功能相同,但具体的实现方式不同时,我们可以通过定义名称相同而形参列表(条件)不同的多个方法,来更好地识别和管理类中的方法。
演示一下方法重载,ReMethodDemo类代码如下:
package csdn.foundation.before_info.method_test; /** * 方法重载的概念: * 同一个类中的多个方法,出现方法名相同,但是参数列表不相同的情况。 * 参数列表不同有以下情况:(有一个不同就可以) //注意和形参的名字无关系 * I.个数不同 * II.对应数据类型不同 * III.相同数据类型但位置不同 * Δ方法重载与方法的返回值类型无关, 与方法的修饰符无关。 */ public class ReMethodDemo { public static void main(String[] args) { int a1 = 3,b1 = 5; long a2 = 8L,b2 = 11L; float a3 = 2.11F,b3 = 9.85F;//小数默认double类型,想定义float类型,需要后面加上一个F。 System.out.println("int类型中,较大的数字是" + compare(a1, b1)); System.out.println("long类型中,较大的数字是" + compare(a2, b2)); System.out.println("float类型中,较大的数字是" + compare(a3, b3)); } public static int compare (int a, int b) { return (a > b)?a :b; } public static long compare (long a, long b) { return (a > b)?a :b; } public static float compare (float a, float b) { return (a > b)?a :b; } public static void compare (int a, float c) {;} }
运行结果:
编辑
六、数组
1.基本概念:
数组是用来存储同一种数据类型的多个元素的容器;此处提到的”数据类型“可以是基本类型,也可以是引用类型,但不能混用。
2.定义格式:
- 格式一:
数据类型[] 数组名 = new 数据类型[长度]; (new关键字用于开辟内存空间;数组长度在定义时指定,不可更改)- 格式二:
数据类型[] 数组名 = new 数据类型[] {元素1,元素2,...}; (定义时元素是确定的,避免了内存空间的浪费)- 格式三:
数据类型[] 数组名 = {元素1,元素2,元素3,...}; (格式三是格式二的变形,简化了代码编写)
ArrayDemo1类代码如下:
package csdn.foundation.before_info.array0; /** * PS : 1) 数据类型[] 数组名 = 数据类型 数组名[] * 两种方式都可以。 * 2) 也可以先声明数组,后分配空间, * eg:int[] aaa; //此处数组实际为null * a = new int[3]; * */ public class ArrayDemo1 { public static void main(String[] args) { // eg:!!!注意格式正确 int[] a1 = new int[5]; //格式1 int[] a2 = new int[]{1, 2, 3, 4}; //格式2 int[] a3 = {1, 2, 3, 4, 5}; //格式3 System.out.println("-------------------------------"); //C中是这样的: int a[] = {1,2}; ,有点类似于Java中的格式三 //数据类型[] 数组名 = 数据类型 数组名[] int aa1[] = new int[3]; int aa2[] = new int[]{1,2,3,4}; int aa3[] = {1, 2, 3, 4, 5}; System.out.println(aa1); //Define a char Array to store 26 English alphabet. char[] alphabets = new char[26]; int i = 0; for ( ; i < alphabets.length; ) { alphabets[i] = (char) ('A' + i); i++; } //print alphabets for (int j = 0; j < alphabets.length; ++j) { System.out.print(alphabets[j] + " "); } } }
运行结果:
编辑
3.数组的访问:
- 通过 索引(也叫下标、脚标)来访问数组,下标是指数组元素距数组起始位置的偏移量,第一个元素的偏移量为0,所以数组的下标从0开始。
- 访问格式:数组名[索引] or 数组名[索引] = 值。
- 若直接手动输出数组变量名,得到的是数组的内地址值。如下图所示:
编辑
- Java中,数组中未手动赋值的元素有默认值;eg:int类型数组默认值是0,double类型数组默认值是0.0。
4.数组的遍历:
通过for循环遍历数组,打印数组中每个元素的值。
PS:数组变量存储的是数组在堆内存中的地址值,而不是数组元素的值,数组变量通过内存地址引用堆内存中的数组,所以数组是引用类型。
演示类ArrayDemo5代码如下:
package csdn.foundation.before_info.array0; import java.util.Scanner; /** * 在Java中,定义一个方法来遍历数组时,只需要将数组名发送给方法即可, * 由于java在内部已经写好了代码,所以方法能够自己找到数组的长度。 */ public class ArrayDemo5 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] arr = new int[5]; System.out.println("请输入数组的元素(5个整数):"); for (int i = 0; i < arr.length; i++) { arr[i] = sc.nextInt(); } System.out.println("_______________________"); System.out.println("数组遍历的结果为:"); printArray(arr); sc.close(); int[] arr2 = new int[5]; for (int i = 0; i < arr2.length; ++i) { arr2[i] = arr[i]; System.out.println("拷贝后的arr2中的第" + (i + 1) + "个元素是:" + arr2[i]); } } public static void printArray(int[] arr) { for (int a = 0; a < arr.length; a++) { System.out.println(arr[a]); } } }
运行结果:
编辑
5.数组的初始化:
- 动态初始化:只指定长度,由系统给出默认值。(定义格式一)
- 整数型(byte, short, int, long):0
- 浮点型(float,double):0.0
- 字符型(char):'\u0000'(空字符)
- 布尔型(boolean):false
- 引用类型:null(空引用)
- 静态初始化:给出初始化值,由系统决定数组长度。(定义格式二、三)
6.Java程序的内存分配:
- 方法区:存储可运行的class文件(字节码文件),包含方法,静态成员,常量等。包含方法的类会被逐个加载到方法区,其中首先加载的是包含main方法的类。
- 栈:方法运行时使用的内存,特点是“后进先出”,即最先进入栈区的方法最后出栈,比如main方法。
- 堆:存储new出来的数组或对象。
- 本地方法栈:JVM在调用操作系统功能时使用,与开发无关。
- 寄存器:CPU使用,与开发无关。
PS:关于“Java程序的内存分配”,我们会在《面向对象》专题(也就是下一个专题)更详细地讲解。有兴趣的同志可以先去看看up写得这两篇博文——
①创建对象的内存图解:java 创建对象的内存图解 (通俗易懂)_java创建对象内存分配图解-CSDN博客
②继承关系的内存图解:java 继承关系的内存图解 (通俗易懂)_java继承的内存模型-CSDN博客
7.数组使用的两个常见问题:
- 数组索引越界异常(ArrayIndexOutOfBoundsException):即下标越界。
- 空指针异常(NullPointerException):数组引用存储的值为null,而非数组的地址。
arrr1 = null; System.out.println(arr1[2]); //运行时报错——java.lang.NullPointerException
8.数组的扩容,缩容,插入元素,插入元素,查找元素:
链接如下:
9.二维数组:
ArrayEX类代码如下:
package csdn.foundation.before_info.array0; import java.util.Arrays; import java.util.Scanner; /* 关于二维数组的声明:(一共三种) 除了像一维数组一样的int[][] twoDiArray = 和 int twoDiArray[][] = 之外, 还有int[] twoDiArray[] = */ public class ArrayEX { public static void main(String []args) { int[][] twoDimensionalArray = { {0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0}, {0, 2, 0, 3, 0, 0}, {0, 0, 0, 0, 0, 0}, }; System.out.println("The length of twoDimensionalArray is :" + twoDimensionalArray.length); System.out.println("The length of twoDimensionalArray's element is :" + twoDimensionalArray[0].length); System.out.println("--------------------------------------"); //traverse the two-dimension array for (int i = 0; i < twoDimensionalArray.length; ++i) { for (int j = 0; j < twoDimensionalArray[0].length; ++j) { System.out.printf("%-5d", twoDimensionalArray[i][j]); } System.out.println(); } System.out.println("--------------------------------------"); for (int i = 0; i < twoDimensionalArray.length; ++i) { System.out.println(Arrays.toString(twoDimensionalArray[i])); } System.out.println("--------------------------------------"); System.out.println(Arrays.toString(twoDimensionalArray)); System.out.println("--------------------------------------"); //Die Demo_two Live Second. Scanner sc = new Scanner(System.in); int rowNum; rowNum = sc.nextInt(); int[][] tDA = new int[rowNum][]; /* Assignment. print every oneDimensionalArray of twoDimensionalArray. */ for (int i = 0; i < tDA.length; ++i) { tDA[i] = new int[i + 1]; for (int j = 0; j < tDA[i].length; ++j) { tDA[i][j] = i + 1; System.out.print(tDA[i][j] + "\t"); } System.out.println(); } sc.close(); } } /** * Actually,the length of twoDimensionalArray's element is uncertain. * It means that the column number of twoDimensionalArray is not decided. * eg: * int[][] twoDimensionalArray; * twoDimensionalArray = new int[5][]; //Don't have to write the width. * 并且,如果没有给一维数组开空间,那么twoDimensionalArray[i] = null; */
运行结果:
编辑
Δ总结
- 🆗,以上就是我们专题一 ——《面向对象之前需要掌握的知识》的全部内容了。感谢阅读!
- 回顾我们的第一个专题,我们先是从“JDK,JRE,JVM”的关系出发,又引出了DOS,IDEA;接着,介绍了Java的一些语法特性,Java的流程控制;最后,又给出了Java的方法和数组的内容,所有内容都相对比较简单,比较容易上手。
- 嗯,总的来说,对于这一专题的内容,大家不需要太上心😂,啥时候忘了回来看看就行,第一个专题就像是安全村,溜达溜达,下一专题开始才是真正的主线。
- 下一专题——《面向对象》,大家不见不散。
System.out.println("END--------------------------------");

