Java Basics 【Oriented Process】

Java 面向过程

by JoianSUN 如鹏网 | Java | 20150705

Java 开发基础

主要内容:

  • 计算机基础常识
  • Java语言介绍
  • Java 开发环境的搭建
  • Eclipse 开发第一个程序
  • Eclipse 个性配置与基本操作

计算机基础常识

计算机的应用

  • 1、科学计算『第一台计算机的诞生』
  • 2、数据处理『数据:图片、文字、音频等;处理:对数据进行的收集、存储、分类、计算、传输等』
  • 3、自动控制
  • 4、计算机辅助技术
  • 5、人工智能–中医专家诊断系统 模拟明医给患者诊病开方
  • 6、多媒体网络应用
  • 7、计算机网络

计算机硬件

计算机硬件是计算机软件运行的基础『物质』。

主要硬件:『CPU、主板、内存、显卡、显示屏等』

计算机软件

软件主要分为两大类:系统软件和应用软件

系统软件(操作系统) 应用软件
DOS(Disk Operating System) Windows Unix Linux Mac 系统软件自带应用『类似计算器、记事本』
Android IOS WindowsPhone 用户自安装应用『QQ、YY、LOL』

P.S.
1)、DOS系统是命令行方式操作系统,为了便于用户的操作,后来产生了图形化界面操作的操作系统,也就是Windows系统
2)、系统软件和应用软件都是用计算机语言编写出来的,计算机语言调用底层指令处理数据

软件开发

1、什么是软件?

软件是一系列按照特定顺序组织的计算机数据和指令的集合。

P.S.
1)、数据就是指现实生活中的年龄、姓名等信息
2)、指令就是告诉计算机如何对数据进行处理

2、软件开发是什么?

借助开发工具与计算机编程语言制作软件

计算机语言

1、自然语言

人与人之间沟通交流的各种表达符号

2、计算机语言

人与计算机之间进行信息交流沟通的一种特殊语言『C\C++、C#、Java、Python、Object-C…』

人机交互

软件的出现实现了人与计算机之间的更好的交互。

两种交互方式:

  • 命令行界面(Command Line Interface CLI):通过控制台输入特定的指令,让计算机完成制定操作。需要记忆大量的指令,较为麻烦,像是早期的DOS系统

  • 图形化界面(Graphical User Interface GUI):为了方便用户的简便操作,由CLI逐渐发展而来交互方式。简单直观,易于接受和上手操作,像是由DOS而来Windows系统

Java语言介绍

Java语言概述

  • 1、Java语言是SUN公司(StanfordUniversityNetwork,斯坦福大学网络公司)1995年
    推出的一门高级编程语言。
  • 2、Java语言是一门面向Internet的编程语言。
  • 3、随着Java技术在web方面的不断成熟,Java语言已经成为Web应用程序的首选开发语言。
  • 4、Java语言是开源『Open Source』完全面向对象,安全可靠,与平台『操作系统』无关的编程语言。

P.S.
Java是允许使用者将应用程序通过Internet从远端服务器传输到本地机上进行执行的一种语言。

Java语言的三种技术架构

1、J2SE(Java 2 Platform Standard Edition)标准版

是为开发普通桌面和商务应用程序提供的解决方案。该技术体系是其他两者的基础,可以完成的一些桌面应用程序的开发,比如Java版的扫雷。

2、J2EE(Java 2 Platform Enterprise Edition)企业版

是为开发企业环境下的应用程序提供的解决方案。该技术体系中包含的技术如Servlet、Jsp等,主要针对于Web应用程序开发。

3、J2ME(Java 2 Platform Micro Edition)小型版
是为开发电子消费产品和嵌入式设备提供的解决方案。该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。

P.S.

1)Java 5.0版本之后,三种架构技术分别更名为JAVASE、JAVAEE、JAVAME。
2)由于现在已经出现了Android、IOS、Windows Phone等手机操作系统,所以J2ME架构基本上已经不再使用了。目前流行的手机软件主要是基于这些最新的手机操作系统进行开发。
3)SUN公司已被Oracle公司收购。

Java语言的特点

Java语言的特点:简单性、解释性、面向对象、高性能、分布式长处理、多线程、动态、安全、体系结构中立、开源『Open Source』跨平台性

1、 开源『Open Source』:开放源代码

2、 什么是跨平台性?

通过Java语言编写的应用程序可以在不同的操作系统平台中运行。亦即可移植性
一次编写, 到处运行『Write Once, Run Anywhere』

P.S.

国内操作系统市场基本已被Windows彻底征服,但国外用户对于操作系统确实有更多的不同的选择项。因此,程序员开发软件的需要考虑到跨平台性,而Java语言就具备了跨平台性的特点。

3、跨平台性的原理是什么?

只要在需要运行Java应用程序的操作系统中,先安装一个Java虚拟机(JVM : Java Virtual Machine) 即可,由JVM来调用操作系统底层指令解析、执行Java程序,从而在该操作系统中运行。

因为有了JVM,所以同一个Java程序在各种不同的操作系统中都可以执行。这样就实现了Java程序的跨平台性,也就是说Java语言具有好的可移植性*。

Java Basics 【Oriented Process】_第1张图片

P.S.

1)、明确:JAVA语言具有跨平台性,但是JVM不具有跨平台性,在不同的操作系统下具有不同版本的JVM
2)、用C\C++语言编写的程序在Windows系统中可以直接运行,在Linux中则不可以。这是因为Windows系统使用C\C++语言编写的,Windows中内置了C\C++的解析器,所以C\C++可以直接在Windows系统中运行。但Java语言编写的程序如果要在Windows系统中运行,就需要在Windows系统中安装一套能够解析、执行Java程序的软件,也就是JVM( Java虚拟机 )。类似的,在Linux、Mac系统中执行Java语言编写的程序也需要安装各自的系统对应的应用。通过这种方式,就实现了Java语言“一次编译,到处运行”的跨平台性。JVM的作用就是搭建了Java语言编写的程序与操作系统之间的桥梁。

Java开发环境的搭建

使用任何一门语言之前必须首先搭建环境。

什么是JRE、JDK

1、 JRE(Java Runtime Environment:Java有运行时环境)

包括Java虚拟机(JVM:Java Virtual Machine)和Java程序所需的核心类库(Java Class Library)。如果想要运行一个开发好的Java程序,计算机中只需要安装JRE就可以了。

2、 JDK(Java Development Kit::Java开发工具包)

JDK提供给Java开发人员使用的,其中主要包含了Java的开发工具以及JRE。所以理论上,安装了JDK就不需要单独安装JRE了。其中的开发工具有编译工具(javac.exe)、打包工具(jar.exe)等。

简而言之:使用JDK开发完成的Java程序交给JRE执行,由JVM保证跨平台性

为什么JDK中包含一个JRE呢?

1)开发完成的Java程序,需要执行得出结果以保证程序的正确性。
2)最重要的是:JDK中的开发工具(如javac.exe、jar.exe等)其实都是Java语言编写的应用程序。为了放方便使用才打包成exe文件。如果没有JRE,那么开发工具是没有办法正常执行的。

总结:
JRE = JVM + 类库(Java Class Library)
JDK = JRE + Java开发工具

Java Basics 【Oriented Process】_第2张图片

JDK的下载和安装

1、下载JDK(Java Development Kit:Java开发工具包)
官网地址: http://www.oracle.com
如鹏网: http://pan.baidu.com/s/1gd3sjnX 提取码:edp7

P.S.
由于SUN公司已经被Oracle公司收购,访问www.java.sun.com时会自动跳转到http://www.oracle.com/technetwork/java.index.html

官网下载示意图下载示意图:

(1)、访问www.oracle.com,点击Downloads下的JavaforDevelopers。

Java Basics 【Oriented Process】_第3张图片

(2)、点击JDK下的DOWNLOAD按钮。

Java Basics 【Oriented Process】_第4张图片

P.S.
8u45代表JDK8版本,45代表子版本,u是update(更新)的缩写。

(3)、在下载之前,首先需要接受JDK的许可证协议,然后再点击jdk-8u45-windows-i586.exe(32位)/jdk-8u45-windows-x64.exe(64位)进行下载。

Java Basics 【Oriented Process】_第5张图片

P.S.
Windowsx86对应的是windows32位系统。
Windowsx64对应的是windows64位系统。

2、安装JDK
(1)、双击“jdk-6u21-windows-i586.exe”文件,点击“下一步”。

Java Basics 【Oriented Process】_第6张图片

(2)、继续点击“下一步”。
默认安装目录为“C:\ProgramFiles(x86)\Java\jdk1.6.0_21\”,可以通过“更改”按钮对安装路径进行自定义至”:\Java\jdk1.6.0_21\” 路径下。

Java Basics 【Oriented Process】_第7张图片

Java Basics 【Oriented Process】_第8张图片

P.S.
安装路径中不要有中文或者特殊符号如空格等,否则后期开发中可能出现一些莫名其妙的错误。

(3)、继续点击“下一步”。

Java Basics 【Oriented Process】_第9张图片

正在安装中…复制文件结束,安装JDK完毕。

(4)、接下来出现的对话框是询问是否安装JRE(Java运行环境),这是可选的,因为JDK中已经包含开发环境和运行环境(JRE)两部分。所以不需要安装,一般情况建议安装,也可以直接点击“取消”按钮。

Java Basics 【Oriented Process】_第10张图片

P.S.
如果你只运行已有的Java程序而不要进行Java程序的开发,那么只需安装JRE即可(因为JRE的体积较小)

如果点击下一步:

Java Basics 【Oriented Process】_第11张图片

(5)、点击“关闭”按钮,安装完毕。

Java Basics 【Oriented Process】_第12张图片

P.S.

  • 1)、JDK无需每次都安装,因为其本身就是绿色版本,可以直接存入U盘,在任何计算机上都可以直接使用。
  • 2)、采用安装的方式使用JDK的好处在于其会在注册表中被注册,当JDK出现新版本,会自动更新

JDK中的命令行工具

1、JDK安装目录下的bin(binary)文件夹是二进制文件所在的目录,其中的exe文件(都是使用java语言编写)都是开发Java程序所需要的命令文件。

Java Basics 【Oriented Process】_第13张图片

Java Basics 【Oriented Process】_第14张图片

P.S.
 这些命令文件并非是图形化方式操作的(双击执行是无效的),而是命令行方式操作的命令文件,所以需要首先打开命令行窗口。

2、打开DOS命令行窗口有两种方式。

(1)、点击”开始”–>”运行”–>”输入’cmd’”–>按下’Enter’键。『直接使用快捷键’Win + R‘』
(2)、点击”开始”–>”所有程序”–>”附件”–>”命令提示符”。
(3)、Win7之后,可以在任意文件夹下,使用Shift + 右键菜单–> 点击”在此处打开命令窗口”。

Java Basics 【Oriented Process】_第15张图片

3、进入到JDK安装目录下的bin目录。

Java Basics 【Oriented Process】_第16张图片

Java Basics 【Oriented Process】_第17张图片

4、输入javac(.exe可以不写),出现如下显示,说明JDK已经可以使用了。

Java Basics 【Oriented Process】_第18张图片

命令行简介

常用的DOS命令
dir(directory):列出当前目录下所有的文件以及文件夹
md(make directory):创建目录
rd(remove directory):删除目录
cd(change directory):进入指定目录
cd .. :退回到上一级目录
cd \ :退回到根目录
del (delete):删除文件或文件夹
cls:清空屏幕内容
exit:退出DOS命令

13个示例轻松掌握常用DOS命令:

(1)、查看D盘下的目录

Java Basics 【Oriented Process】_第19张图片

(2)、查看指定文件夹下的目录使用cd 文件夹名称的时候,输入到一定长度,可是使用Tab键快速补全。

当输入到“Baidu”的时候,使用Tab键补全,获取的是以”Baidu”开头的所有文件夹的第一个(按照字符编码顺序列出所有”Baidu”开头的文件夹)

Java Basics 【Oriented Process】_第20张图片

(3)、通过通配符的方式更方便的进入指定文件夹

Java Basics 【Oriented Process】_第21张图片

P.S.

“cd Baidu*”命令中的”*”是一种通配符『代表一个或多个字符』,如果当前目录中有多个文件夹名称都能匹配,那么会自动进入第一个名称匹配的文件夹中。

(4)、退回上一级目录

Java Basics 【Oriented Process】_第22张图片

(5)、退回到根目录

Java Basics 【Oriented Process】_第23张图片

(6)、在D盘根目录下创建新的文件夹。

Java Basics 【Oriented Process】_第24张图片

P.S.
早期操作计算机用DOS操作,因为需要记忆太多的命令,不利于普及,后期发展成图形界面,通过鼠标点击界面的形式操作计算机,底层实际上运行的依然是DOS命令。

(7)、删除文件夹

Java Basics 【Oriented Process】_第25张图片

(8)、新建文件夹,并在此文件夹下创建一个文件,由于此文件夹非空,删除文件夹失败。『Windows 防止误删除采用的机制』

Java Basics 【Oriented Process】_第26张图片

(9)、只有将文件夹下的所有文件和文件夹删除,才能删除该文件夹

Java Basics 【Oriented Process】_第27张图片

P.S.

  • del *del *.*命令表示删除当前目录下的所有文件。
  • Windows系统删除文件是从内向外删,文件夹内部的文件如果没有完全删除,文件夹删除必定会失败。
  • 使用rd /s 『提示是否确认删除』或rd /q /s『不提示直接删除』。

Java Basics 【Oriented Process】_第28张图片

(10)、输入help命令,可以查询所有命令功能

Java Basics 【Oriented Process】_第29张图片

(11)、输入help命令,查询指定命令功能

Java Basics 【Oriented Process】_第30张图片

(12)、输入cls命令,可以清空当前屏幕内容

Java Basics 【Oriented Process】_第31张图片

(13)、输入exit命令,退出命令行工具!

Java Basics 【Oriented Process】_第32张图片

环境变量的配置

之前在使用的时候,必须保证已经编写的.java文件必须和javac.exe在同一个目录下才可以正常的编译,这将会导致bin文件夹越来越乱,给bin目录下的文件内容带来了误删除的隐患。

Java Basics 【Oriented Process】_第33张图片

为了能够在DOS命令行窗口中,在任何目录下都可以执行javac命令,就需要将javac.exe命令文件所在目录放在path环境变量中。

原理:
在DOS命令提示符窗口中输入某一个命令后,Windows系统会首先在当前目录下.查找是否有命令可以执行。如果没有,Windows系统就会在path环境变量路径中查找。如果查找到,就会执行该命令。如果还没有找到,那么就会提示如下信息。

1、如何配置环境变量

(1)、右击“计算机”–>“属性”。
(2)、点击“高级系统配置”–>“高级”选项卡–>“环境变量”
(3)、将javac命令文件所在目录的路径放入path路径中,使用英文”;”分割。

 P.S.

  • 1)、一定要将javac命令文件所在目录的路径放入path环境变量的开头。否则,如果计算机上以前已经安装了其他版本的JDK并且也已经配置了path环境变量,那么先执行的javac命令就是以前的JDK安装目录下的javac命令。因为windows系统是按照path路径从头向后搜索各个目录的。
  • 2)、环境变量中的各个路径之间一定要以分号进行分隔。
  • 3)、设置path环境变量的时候千万不要删除掉原来的内容。否则,很多程序将无法运行。

(4)、点击确定。然后,一定要新开一个新的DOS命令行窗口,再输入javac命令,如果出现如下显示,说明path环境变量配置成功。

Java Basics 【Oriented Process】_第34张图片

P.S.
如果一台计算机上安装了多个版本的JDK,通过javac-version可以确定当前使用的JDK版本。

Java Basics 【Oriented Process】_第35张图片

2、环境变量配置技巧

(1)、新创建一个环境变量JAVA_HOME记录jdk安装目录的路径

Java Basics 【Oriented Process】_第36张图片

Java Basics 【Oriented Process】_第37张图片

(2)、在path环境变量中通过“%%”动态的获取JAVA_HOME的值即可

Java Basics 【Oriented Process】_第38张图片

通过这种方式,如果JDK安装目录改变了,那么只需要修改JAVA_HOME环境变量即可,而不用再修改path环境变量。

P.S.
 %JAVA_HOME% 表示动态获取名称为JAVA_HOME环境变量的值。

3、环境变量临时配置方式

如果在别人的计算机上进行Java程序的开发,设置path这样的系统环境变量就不太好,那么就可以采用设置临时环境变量的方式(通过DOS命令中set命令完成)。

(1)、用set命令查看本机的所有环境变量的信息。

Java Basics 【Oriented Process】_第39张图片

(2)、用set命令(”set 变量名”)查看具体某一个环境变量的值。

Java Basics 【Oriented Process】_第40张图片

(3)、用set命令(”set 变量名=”)清空一个环境变量的值。

Java Basics 【Oriented Process】_第41张图片

(4)、用set命令(”set变量名=具体值”)给指定环境变量定义具体值。

Java Basics 【Oriented Process】_第42张图片

(5)、想要在原有环境变量值基础上添加新值。

首先,通过“%变量名%”操作符获取到原有环境变量的值。然后,追加上新值,再赋值给该变量名即可

Java Basics 【Oriented Process】_第43张图片

 P.S.
临时配置环境变量的方式只在当前DOS命令行窗口有效。窗口关闭,配置即消失。

Eclipse编写第一个程序

编写运行Hello World

『开发工具编写好的Java源代码,由javac.exe进行编译,得到的.class字节码文件,交由java.exe解释执行,输出到Console控制台』

(1)、使用Win + R,输入notepad,调用记事本,输入以下代码:

class Demo
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

P.S.

1)HelloWorld:代表学习计算机语言的第一个入门小程序。现在泛指接触任何新事物的第一步。
2)class:是java中的关键字,用于定义类,java语言的程序代码都需要定义在类中。
3)关键字:被java语言赋予了特殊含义的单词,高级记事本中具有高亮显示『class、public、static、void』。
4)Demo:为了方便使用这个类,给类自定义的类名。
5){ }:定义该类中代码的范围。
6)main方法的作用在于保证一个类可以独立运行,因为它是程序的入口。
7)System.out.print();语句用于告诉系统输出打印数据,可以将括号中的内容打印在控制台上。通过该语句可以直接在控制台看到jvm运行java程序后的结果

另请注意:

 1)、写代码,阅读性第一,功能性第二,一定要注意写代码的格式
 2)、源文件名和类名可以不一致,但当class前有修饰符public时,则必须一致
————————————————————————————-自行验证

(2)、通过javac命令对该java文件进行编译。

 ① 有了java源文件,将其编译成JVM可以识别的文件。
 ② 在该源文件目录下,通过javac编译工具对Demo.java文件进行编译。
 ③ 如果程序没有错误,没有任何提示,就会在当前目录下出现一个Demo.class文件,该文件称为字节码文件,也就是可以执行的java的程序。

Java Basics 【Oriented Process】_第44张图片

(3)、通过java命令对生成的class文件进行运行。

Java Basics 【Oriented Process】_第45张图片

P.S.
 使用java命令运行class文件,没有必要加上.class文件后缀

(4)、javac命令的作用是对java程序进行语法性检查,一旦出错,就会打印出错误信息。

Java Basics 【Oriented Process】_第46张图片

由于System.out.println("hellojava")语句后面缺少分号,所以报错。根据报错的行数,找到错误的地方,进行修改。然后重编编译,运行。

Java Basics 【Oriented Process】_第47张图片

(5)、java命令可以启动JVM,然后找到相应的class文件,再寻找程序入口,也就是main方法,然后调用该方法执行java程序


常见错误信息–找不到文件

Java Basics 【Oriented Process】_第48张图片

错误可能原因:

 1)文件名写错。
 2)类文件不在当前路径下或者不在classpath(后面会将讲到)指定路径下。
 3)后缀名问题。

“ 后缀名问题”查找及解决方案如下:

  • 点击“工具”–>“文件夹选项”–>点击“查看”选项卡,并且勾选掉“隐藏已知文件类型的扩展名”。

  • 然后就可以看到文件真正的后缀名为txt,所以找不到Demo.java文件。只需将修改后缀名为 “.java”,再重新编译、运行即可。


配置classpath环境变量

由于可能频繁执行多个class文件,并且多个class文件可能存储在不同的目录下,那么每次都在命令提示符窗口中切换目录会相当的麻烦。

classpath环境变量的作用类似于path环境变量,但是它的作用在于告诉JVM去哪里找到class文件。

JVM查找类文件的顺序:

  • 1)、如果没有配置classpath环境变量,JVM只在当前目录下查找要运行的类文件。
  • 2)、如果配置了classpath环境,JVM会先在classpath环境变量值的目录中查找要运行的类文件。

示例:

1)、 在C盘根目录下新创建一个文件夹,命名为myclass,将C:\code目录下的Demo.class文件复制到此文件夹下。

copy srcDirectory destDirectory;

Java Basics 【Oriented Process】_第49张图片

2)、 将C:\code文件夹中的源文件Demo.java修改为在控制台中打印 “你好,世界”,重新编译,生成Demo.class。

Java Basics 【Oriented Process】_第50张图片

3)、如果想要执行C盘根目录下myclass文件夹中的Demo.class,又不想切换目录,由于JVM会先在classpath环境变量值的目录中查找要运行的类文件,可以通过设置环境变量classpath为“c:\myclass”实现。

set classpath=C:\myclass

示例:

1)、 删除C:\myclass目录下的Demo.class。

del C:\myclass\Demo.class

2)、 在C:\code目录下运行Demo.class文件,报错。 

Java Basics 【Oriented Process】_第51张图片

这是因为classpath环境变量已经被赋值,所以即使在 C:\code目录下存在Demo.class文件,JVM也根本不会去查找。

3)、classpath环境变量值的结尾处如果没有分号,那么JVM在classpath目录下没有找到要指定的类文件,也不会在当前目录下查找。即使当前目录下有,也不会运行。

4)、classpath环境变量值的结尾处如果加上分号,那么JVM在classpath目录下没有找到要指定的类文件,会在当前目录下再查找一次.


示例:

 为环境变量classpath赋值后加上 “;” 分号,然后在C:\code目录下运行Demo.class文件,由下图可见,运行成功。

Java Basics 【Oriented Process】_第52张图片

P.S.

  •  建议配置classpath环境变量时,值的结尾处不要加分号,如果需要访问当前目录可以用“.”(代表当前目录)表示,这样可读性更好一些。
set classpath=.;%classpath%

Java Basics 【Oriented Process】_第53张图片


Eclipse个性配置与基本操作

Eclipse个性化配置

  • 1)、中文字体太小:窗口(Window)→首选项(Preferences)→常规(General)→外观(Appearance)→颜色和字体(Colors and Font)→基本(Basic)→双击“文本字体(Text Font)”在弹出窗选择“Courier New”。
     
  • 2)、我喜欢大括号在同一行:首选项→Java→代码样式(CodeStyle)→格式化程序→编辑(Edit)→花括号(braces),都选“下一行”。写一个名字保存。
     
  • 3)、配置项目的Java编译器版本:项目右键→属性→Java编译器(Compiler)→启用特定于项目的设置,选择相应版本,建议选择1.7以上,后续讲课也默认1.7。
     
  • 4)、配置java的源代码,方便研究java类库源码、文档:首选项→Java→已安装的JRE→双击JRE→展开rt.jar→源代码链接,选择JDK中的src.zip。
     
  • 5)、快捷键Ctrl+shift+F格式化代码(如果没反应可能是和别的软件热键冲突,比如搜狗拼音,在输入法条中点击右键“设置属性”→“按键”→“系统功能快捷键”,看到了吗,把所有都取消吧);Alt+/智能提示;Ctrl+鼠标查看定义。

关于Eclipse中的项目和工作空间

1)、切换工作空间的方法:退出重启,如果勾选了【将此值用作初始值并且不再询问】,则文件(File)→切换工作空间(switch workspace),从“工作空间”列表中选择(之前打开过的)或者浏览选择工作空间根目录(包含.metadata)。

2)、如何导入别人的项目到工作空间中:包资源管理器(Package Explorer)→导入(Import)→常规(General)→现有项目到工作空间中(Existing Projects into Workspace),对话框中选中“选择根目录(Select Root Directory)”→【浏览】→选择项目的根目录(包含.project文件)或者WorkSpace,选择要导入的项目即可。

Java语法基础

主要内容涉及到的是:

  • Java语言基础由关键字、标识符、注释、常量和变量、运算符、语句、方法和数组等组成。

关键字(Key Words)

定义及组成

定义:被Java语言赋予特定含义的单词。
特点:组成关键字的字符全部是小写的。

全部关键字

Java Basics 【Oriented Process】_第54张图片
Java Basics 【Oriented Process】_第55张图片

注意:const和goto作为保留字,暂时不可使用。可能在JDK更高的版本中,提升为关键字

// 蓝色字体就是关键字
public class Demo
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

P.S.
1、所有的关键字都不需要记忆,在后期的学习中会慢慢的掌握的
2、类名的首字母要大些,这是Java命名规范之一
3、写代码一定要注意代码规范,注重代码的阅读性
4、命名时,要做到见名知意,例如Abc就不是友好,Demo则可以

标识符(Identifier)

定义以及组成

定义:程序中自定义的一些名称。类、方法、接口、变量等起名字的字符序列。
组成:26个大小写字母、0~9数字、_和$

合法标识符规则

  • (1)、数字不可以开头,例如:2Demo是不合法的
  • (2)、不可以使用关键字,例如:public就不可以,public是关键字
  • (3)、不可以使用除了_$之外的特殊字符

P.S.
1)、Java中严格区分大小写,例如:Demo和demo是不同的
2)、在起名字时,尽量做到见名知意,提高代码的阅读性
3)、公司中经常使用_代表某一类名称,例如:_temp。通过$分割主名称和子名称,例如:TrafficLamp$Red。

Java名称命名规范

(1)、 包名命名规范

『包:相当于是Windows下的文件夹,用于解决相同类名问题』
包名必须均为小写。包名需要使用英文说明包内代码功能,最好不要采用拼音。

  • 以com.rupeng.elec.web为例:
  • 第一段 com代表公司,org代表组织
  • 第二段 rupeng为公司名称 如鹏
  • 第三段 elec为项目名称
  • 第四段 web为模块名称(分层)

(2)、类名命名规范

Java类名称必须以大写字母开头,可以使用2-4个英文单词(尽量不要用缩写)组成每个单词的首字母大写。文件名称必须能说明文件内代码功能。

  • java类大致分为接口,实现类,模型,静态类型声明,逻辑类,工具类。
  • 接口类命名:IXxx。
  • 实现类命名:XxxImpl。 实现类的名称前段必须与接口一致说明是哪个接口的实现。
  • 持久层类:XxxDao
  • 业务层类:XxxService
  • Action:XxxAction
  • Servlet:XxxServlet
  • 工具类:如StringUtil,DateUtil等。
  • 也可以:StringTools
  • java里面的 Arrays 和 Collections

(3)、方法名命名规范

  • 方法名应该能够简单描述出该方法实现的功能,如deleteUser
  • 方法名尽量不使用缩写,除非它是众所周知的,如可以使用db表示database
  • 方法名可以有两个或三个单词组成,但尽量不要多于三个以上
  • 方法名中由多个单词合成,第一个单词通常为动词,首字母小写,中间的每个单词的首字母都要大写,如删除用户:deleteUser
  • 方法名中不要使用下划线

(4)、变量名命名规范

  • 在程序中变量的名称要求能够体现出变量的功能,如果是单个单词那么变量名用小写,例如:email。
  • 如果变量名是多个单词组成那么首字母小写,中间的每个单词的首字母都要大写。例如:isSuperUser; userLogin
  • 如果是循环变量,那么变量名必须是一个小写字母,如:i,j,k。
  • 变量名也尽量不使用缩写,且一定要有含义,不能使用没有表达意义的变量名,如:a1; a2; mmm。

(5)、常量名命名规范

常量名也应当有一定的意义,常量名字母全部大写。如果是由多个单词构成,可以用下划线隔开

  • private final int PI=3.1415926;
  • int YEAR;
  • String TITLE = “xxxx”;
  • int WEEK_OF_MONTH = 0;

注释

定义以及特点

定义:由于注解说明解释程序的文字。
特点:提高了代码的阅读性。

Java中的注释格式

(1)、单行注释

格式:
    // 说明文字

(2)、多行注释

格式:
    /*  
     *  说明文字  
     */

(3)、文档注释『Java特有』

格式:
    /**
     * 说明文字
     * @author JoianSUN 
     */

示例:

/**
 *  我的 Hello World 程序。
 *  @author JoianSun 
 */
class Demo
{
     /*
      * 主函数,是程序的入口。
      * 它的出现可以保证程序的独立运行。
      */
    public static void main(String[] args)
    {
        // 输出语句用于将括号内的数据打印到控制台。
        System.out.println("Hello World");
    }
}

P.S.
1)、对于单行和多行注释,被注释的文字,不会被JVM(java虚拟机)解释执行。所以,即使添加再多的注释,编译后生成的class文件占用硬盘字节多少不变。

2)、对于文档注释,是java特有的注释,其中注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档。

3)、注释是一个程序员必须要具有的良好编程习惯。初学者编写程序必须养成习惯:先写注释再写代码

4)、将自己的思想通过注释先整理出来,再用代码去体现,因为代码仅仅是思想的一种体现形式而已

5)、单行注释可以嵌套单行注释,单行注释可以嵌套多行注释,多行注释可以嵌套单行注释。但是,多行注释不能嵌套多行注释,因为多行注释的开头会和被嵌套的多行注释的结尾配对,导致后面的注释失效。

6)、可以使用注释对代码中的错误进行定位
方法:当程序运行报错时,将某些代码注释掉,然后重新编译,运行。如果程序不再报错,那么说明注释掉的部分代码中包含错误代码。

常量

定义

定义:程序执行过程中其值保持不变。

Java中常量的分类

1、字面值常量:

  • 1)、整数常量:所有整数。 
  • 2)、小数常量:所有小数。
  • 3)、布尔(boolean)型常量:只有两个数值,true、false。
  • 4)、字符常量:将一个数字字母或者符号用单引号(’’)标识,如:’a’。
  • 5)、字符串常量:将一个或者多个字符用双引号(“”)标识,如:”helloworld”、”a”、”“(空字符串)。
  • 6)、null常量:只有一个数值就是:null。

2、自定义常量(final关键字时讲解)

进制的由来

对于整数,有四种表现形式:

  • 二进制:0-1,满2进1。
  • 八进制:0-7,满8进1,用0开头表示,如:012。
  • 十进制:0-9,满10进1。
  • 十六进制:0-9,A-F,满16进1,用0x开头表示。如:0x4A2C。

任何数据在计算机中都是以二进制的形式存在的,二进制早期由电信号开关演变而来。一个整数在内存中一样也是二进制的,但是使用一大串的1或者0组成的数值进行使用很麻烦。所以就想把一大串缩短点,将二进制中的三位用一位表示。这三位可以取到的最大值就是7,超过7就进位了,这就是八进制。但是对于过长的二进制变成八进制还是较长,所以出现的用4个二进制位表示一位的情况,四个二进制位最大是15,这就是十六进制。

规律:进制越大,表现形式越短。

P.S.

  • 1Byte=8bit
  • 1KiB=1024Byte
  • 1MiB=1024KiB
  • 1GiB=1024MiB

进制的基本转换

(1)、十进制转二进制

原理:对十进制数进行除2运算。

示例:求十进制数6的二进制数。

6/2=3余0 
3/2=1余1
1/2=0余1
故,6(十进制)=110(二进制)。

(2)、二进制转十进制

原理:二进制乘以2的过程。

示例:求二进制数110的十进制数。

110= 0*20 + 1*21 + 1*22 = 0 + 2  +  4 = 6
附:括号中的数值代表次方。

(3)、十进制转八进制

原理:八进制,其实就是二进制位,3个二进制位,1个八进制位。

示例:求十进制数43的八进制数。

十进制43
二进制101011
三位分割000-101-011
八进制053
因此,43(十进制)=101011(二进制)=053(八进制)。

(4)、十进制转十六进制

原理:十六进制,其实就是二进制位,4个二进制位,1个十六进制位。

示例:求十进制数43的十六进制数。

十进制43 
二进制101011
四位分割0010-1011 
十六进制2(2)11(B)
因此,43(十进制)=101011(二进制)=0x2B(十六进制)

负数的进制

原理:负数的二进制表现形式就是对应的正数二进制取反加1。

示例:求-6的二进制表现形式,其实就是对应的正数6的二进制取反加1。

6 
00000110 
取反:11111001
加 1:00000001
——————–
11111010

P.S. 负数的二进制最高位永远是1。

变量

概念

定义:内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型),该区域的数据 可以在同一类型范围内不断变化。

特点:变量其实就是将不确定的数据进行存储,也就是需要在内存中开辟一个空间。

为什么要定义变量?

用来不断存放同一类型的常量,并可以重复使用

定义变量的格式: 数据类型 变量名 = 初始值 ;

例如:byte b = 3;

P.S.
1)、格式是固定不变的,记住格式,以不变应万变
2)、变量的作用域(一对 { } 之间有效)
3)、变量只能存放某一种类型的数据

Java语言的数据类型

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

类型 字节数
byte 1
short 2
int 4
long 8
float 4
double 8
char 2
boolean 1

 
Java语言的数据类型包括8种基本类型、3种引用类型。

Java Basics 【Oriented Process】_第56张图片

P.S.
1)、整数默认类型:int类型; 小数类型默认:double类型 【很重要】
2)、double类型的小数值精度比float类型的小数更高。

常见错误

错误示例1:

class VarDemo
{
    public static void main(String[] args)
    {
        byte b = 3;
        byte b = 8;
    }
}

运行结果:“错误:已在方法中 main(String[] ) 中定义了变量b”

错误原因:同一个作用域中,同一个变量名只可以定义一次。


错误示例2:

class VarDemo
{
    public static void main(String[] args)
    {
        long l = 123456789123;
        System.out.println(l);
    }
}

运行结果: “错误: 过大的整数:123456789123”

错误原因:由于整数类型默认是int类型,如果超过了int类型的范围,那么就会报错。即使是赋给long类型的变量,但是由于后面的常量已经超出了int的范围,同样导致错误。

解决方案:在数值后面加上一个L或l(建议使用'L',可识别度 更高),就可以让编译器知道后面的常量是long类型的。

long l = 123456789123L;

错误示例3:

class VarDemo
{
    public static void main(String[] args)
    {
        float f = 3.14;
        System.out.println(f);
    }
}

运行结果:“错误:不兼容的类型:从double转换到float可能会有损失”

错误原因:由于小数类型默认是double(8 byte)类型,赋值给float(4 byte)类型的变量,可能会损失精度,所以编译通不过。

解决方案:在数值后面加上一个F或f(建议使用'F')让编译器知道后面的常量是float类型

float f = 3.14F;

错误示例4:

class VarDemo
{
    public static void main(String[] args)
    {
        int y;
        System.out.println(y);
    }
}

运行结果:“错误:可能尚未初始化变量y”

错误原因:变量需要必须先初始化,才可以使用


错误示例5:

class VarDemo
{
    public static void main(String[] args)
    {
        int y = 1;
    }
    System.out.println(y);
}

运行结果:“错误:需要标识符”

错误原因:变量在其作用域{ }之内才有效,可以使用。System.out.println(y); 已经超出了 变量y 的作用域,所以 此处的 y 是没有定义的。需要定义标识符 y 。


错误示例6:

class VarDemo
{
    public static void main(String[] args)
    {
        char ch = 'a';
        System.out.println(ch);
    }
}

运行结果:“错误:非法标识符:’\uff1b’”。

错误原因:编写程序时,不能使用中文符号。 char ch = 'a';中的’;’ 是中文下的分号。


类型转换

类型转换在开发中也很常用,简单来说就是类型之间相互的转化,类型转换共分两种,自动类型转换『隐式类型转换』和强制类型转换『显示类型转换』。

(1)、自动类型转换『隐式类型转换』

定义:自动类型转换就是不需要我们手动对类型来进行强制转换。从小到大的转换

byte,short,char–>int–>long–>float–>double
byte,short,char三者之间不进行任何转换,运算时,先转换为 int 再运算

示例:

class VarDemo
{
    public static void main(String[] args)
    {
        int x = 3;
        byte b = 5;
        x = x + b;
        System.out.println(x);
    }
}

运行结果: 8

Java Basics 【Oriented Process】_第57张图片

说明:int类型的变量占4个字节,当byte类型的变量与其相加的时候,首先会将byte类型的变量自动转化为4个字节的int类型,然后再进行加法操作。

(2)、强制类型转换『显示类型转换』

定义:强制类型转换需要把类型进行手动转换,否则无法正常使用。是一种从大到小的转换

示例:

class VarDemo
{
    public static void main(String[] args)
    {
        byte b = 3;
        b = b + 200;
        System.out.println(b);
    }
}

运行结果:“错误:不兼容的类型:从int转换成byte可能会有损失”

错误原因:当byte类型的变量提升为int类型和int类型的常量200进行相加后,结果依然是int类型,再赋值给byte类型,当然会出现损失精度的错误。

解决方法:进行强制类型转换,也就是将占4个字节的int类型值,再强硬存储到占1个字节的byte变量中。

代码如下:

b = (byte)(b + 200);

运行结果: -53

说明:结果为-53的原因是,200+3结果是int类型的203,也就是二进制(四个字节)的 00000000 000000000 00000000 11001011,截取成占1个字节空间的byte类型的二进制也就是11001011。由于首位为1,所以是负数,转换为原码:除符号位外,其余部分取反加1,得1,0110101,原值是 -(00110101)即-53。

Java Basics 【Oriented Process】_第58张图片

P.S.
明确:只有数值类型才能进行四则运算,非数值类型不可以

示例:

class VarDemo
{
    public static void main(String[] args)
    {
        System.out.println(true + 1);
    }
}

运行结果:“错误:二元运算符 “+” 的操作数类型错误 【第一个类型:int 第二个类型:boolean】”

P.S.
明确:字符’0’的数值:49 字符’a’的数值:98 字符’A’的数值:66
char 类型数据也可以和 int 类型相加,但是首先 char 类型数据会被自动提升为 int 类型。

示例:

class VarDemo
{
    public static void main(String[] args)
    {
        System.out.println('a' + 1);
        System.out.println('你' + 1);
    }
}

运行结果:
98
20321

说明:字符类型数据之所以能够自动提升为int类型是因为字符类型数据在计算机中也是用0、1表示的,int类型数据在计算机中也用0、1表示,所以char类型数据当然可以转换为int类型数据。但是,字符类型数据在计算机中使用0、1表示是按照何种顺序组合排列的则需要依据某个码表而定。Java中的内置码表是Unicode,既包含中文,也包含英文。

P.S.
通过强转也可以把数字强转成字符。

示例:

class VarDemo
{
    public static void main(String[] args)
    {
        System.out.println((char)('a' + 1));
    }
}

运行结果: b

表达式的数据类型自动提升:

  • 所有的byte型、short型和char的值将被提升到int型
  • 如果一个操作数是long型,计算结果就是long型
  • 如果一个操作数是float型,计算结果就是float型
  • 如果一个操作数是double型,计算结果就是double型

面试题

1、说出报出如下错误的原因:

class VarDemo
{
    public static void main(String[] args)
    {
        byte b = 3 + 7;
        byte b1 = 3;
        byte b1 = 7;
        b = b1 + b3;
        System.out.println(b);
    }
}

运行结果:“错误:不兼容的类型:从int转换成byte可能会有损失”

错误原因:涉及到编译器编译程序时候的细节,之所以byte b=3+7;,没有报错,是因为3和7都是常量,编译器知道结果是10,并且在byte范围之内,因此就自动进行了强转,所以不会报错『如果是3+187的话,会报错:可能会损失精度』。而b=b1+b2;中b1和b2都是变量,编译器编译程序是一行一行编译的,它根本不知道b1和b2到底是多少,两个byte类型的数据相加时,首先都会被提升为int类型,他们的和也是int类型,其值可能会超过byte的范围,因此就会报错。

常量值的计算是在编译期间完成,变量值的运算是在运行时确认

而以下程序不会报错:

class VarDemo
{
    public static void main(String[] args)
    {
        int x;
        int x1 = Integer.MAX_VALUE;
        int x2 = 2;
        x = x1 + x2;
        System.out.println(x);
    }
}

说明:原因是因为int类型的两个变量相加,最后还是int类型,虽然结果溢出,但是编译时不会报错,因为是运行时错误。

2、说明以下问题:

byte b = 130 ; 可否通过编译?为什么?如何改进?改进之后的结果又是多少呢?请说明原因?

  • 参看”(2)、强制类型转换『显示类型转换』”示例

3、写出以下代码片段的结果:

System.out.println("hello" + 'a' + 1);
System.out.println('a' + "hello" + 1);
System.out.println('a' + 1 + "hello");

解答:
    helloa1
    ahello1
    99hello


4、问答题:Java语言中char是否可以存储中文汉字,为什么?

解答:可以,因为中文汉字是2个字节组成,而Java中的char也是2个字节长度

Java 语言使用的是 全球语言统一编码(Unicode)

运算符

算术运算符

Java Basics 【Oriented Process】_第59张图片

示例1:

class OperatorDemo
{
    public static void main(String[] args)
    {
        int x = 23;
        x = 23 /12 + 1;
        System.out.println(x);
    }
}

>>>   2 

说明:整数与整数相除的结果,永远是整数,小数部分被忽略!

示例2:

class OperatorDemo
{
    public static void main(String[] args)
    {
        System.out.println(-5 % 2);
        System.out.println(-5 % -2);
        System.out.println(5 % 2);
        System.out.println(5 % -2);
    }
}

>>>   -1
      -1
       1
       1

说明:负整数与任意非0整数取余的结果是负整数;正整数与任意非0整数取余的结果是正整数!

示例3:

class OperatorDemo
{
    public static void main(String[] args)
    {
        int a = 3;
        int b = a++;
        System.out.println("a = " + a + " b = " + b);
    }
}

>>>>   a = 4 b = 3

说明:计算机中的实际操作是:当执行b = a ++语句时,先把a的值放在一个临时内存空间中,然后将 a 自身加1,再将内存空间中的a赋值给b,因此b还是a原来的值,也就是3(注意:使用的是左运算

示例4:

class OperatorDemo
{
    public static void main(String[] args)
    {
        int a = 3;
        int b = ++a;
        System.out.println("a = " + a + " b = " + b);
    }
}

>>>   a = 4 b = 4

说明:当执行语句b = ++a时,现将a的值加1,再将a赋值给b,也就是4 .


赋值运算符

符号:=、+=、-=、*=、/=、%=

明确:a += b 的作用 相当于 a = a + b;(其它运算符 同理类比)
因为各种赋值运算符,具有相同性质,重点解析+=

示例1:比较 s = s + 4 和 s += 4 的区别

class OperatorDemo
{
    public static void main(String[] args)
    {
        short s = 3;
        s = s + 4;
        System.out.println("s = " + s);
    }
}

运行结果:“错误:不兼容的类型:从int转换成int可能会有损失”

说明:在执行s=s+4;语句时,编译器在编译的时候,默认并没有强制类型转换。所以,s是short类型,4是int类型,s会自动提升为int类型,相加的和也是int类型,赋值给short类型的变量必然造成损失精度的错误。这时候就需要进行强制类型转换: s = (short)(s + 4);* *


那如果将 s = s + 4; 替换为 s += 4;,结果又会是什么样子的呢?

运行结果:s = 7 ;这是为什么呢?

说明:在执行s+=4;语句时,编译器在编译的时候,默认进行了强制类型转换,也就是将int类型的数据转换成short类型的数据。

s+=4; 等价于 s = (short)(s + 4); 而非 s = s + 4;


比较运算符

Java Basics 【Oriented Process】_第60张图片

P.S.
比较运算符结果是boolea类型值 也就是 true 或 false
注意比较 ===

示例1

class OperatorDemo
{
    public static void main(String[] args)
    {
        int a = 3;
        int b = 2;
        boolran c = true;
        System.out.println(a > b);
        System.out.println(a == b);
        System.out.println( c = false);
        System.out.println( c == false);
    }
}

>>>   true
      false
      false
      false

说明:前面打印的两句很好理解,重点是后两句,虽然都是false但是完全不同,第三句打印的是c的新值false,第四句打印的是c和false等于比较的结果

// System.out.println( c = false);
// 实际上等价于:先赋值、再打印c的新值
c = false;
System.out.println(c);

逻辑运算符

Java Basics 【Oriented Process】_第61张图片

逻辑运算符用于连接两个boolean类型的表达式

运算规律:

  • &:同为true结果为true,否则false
  • | :存在为true结果为true,否则false
  • ^ :相同为false,不同为true
  • ! :!(true)为false,!(false)为true,!!(true)=true
  • &&:同为true结果为true,否则false
  • ||:存在为true结果为true,否则false

重点在于比较&&&以及|||的区别

1、&&&运算结果一样
2、&&具有短路的效果,当左边为false,右边的不参与运算,提高效率;& 不具有短路效果,无论左边的是否为false,右边依然参与运算


1、|||运算结果一样
2、||具有短路的效果,当左边为true,右边的不参与运算,提高效率;| 不具有短路效果,无论左边的是否为true,右边依然参与运算


鉴于运行效率,使用中,多为 "&&" 和 "||"

示例:

class OperatorDemo
{
    public static void main(String[] args)
    {
        int x = 3;
        int y = 6;
        System.out.println("x = " + x + " y = " + y);
        if( y > 5 & (++x) == 5 )
        {
            System.out.println("Hehe");
        }
        System.out.println("x = " + x + " y = " + y);
    }
}

>>>   x = 3 y = 6
      x = 4 y = 6

说明:结果显示 if 语句块并没有执行,但是x的值加1,因为&没有短路,换成&&,结果又会怎样呢? x的值还是3

位运算符

Java Basics 【Oriented Process】_第62张图片
Java Basics 【Oriented Process】_第63张图片

P.S.
位运算符是直接针对二进制位进行运算。

  • &运算的例子:
      6 & 3 = 2
    110与011按位&得到010,也就是十进制下的2

用“与运算”可以很方便的获取某一个二进制数的其中其中几位数。

例如:获取17476二进制数的后四位
   0100 0100 0100 0100
0000 0000 0000 1111
—————————————
    0000 0000 0000 0100

  • |运算的例子:
      6 | 3 = 7
    110和011按位|得到111,也就是十进制下的7

  • ^运算的例子:
      6 ^ 3 = 5
    110和011按位|得到101,也就是十进制下的5

一个数异或 同一个数两次,结果还是这个数

  • 6 ^ 3 ^ 3 = 6
    011和011异或的结果是000,再和6进行异或就是6本身

技巧:利用异或运算可以实现数据简单地进加解密,例如对一张图片的所有数据异或3加密,那么这幅画就无法查看了,解密只需要再对图片的数据执行异或3操作即可。

  • !运算:取反操作就是对二进制数值的每一位0变1,1变0。

  • <<运算的例子:
      3 << 2 = 12 相当于 3 * 22 = 12
      3 << 3 = 12 相当于 3 * 23 = 24

总结:

  • 左移几位其实就是该数据乘以2的几次方。
  • <<:可以完成2的次幂的运算
  • >>运算的例子:
      6 >> 1 = 3 相当于 6 / 22 = 3
      6 >> 2 = 2 相当于 6 / 23 = 2

总结:右移几位其实就是该数据除以2的几次方。

  • >> 右移:高位出现的空位,原来是什麽就用什么来填补
  • >>> 无符号位右移:高位出现的空缺永远用0来填补
    -24 >> 2 = -6
    -24 >>> 2 = 1073741818

PS:计算机中乘除法的原理:左移、右移


面试题

1、最有效率的方式算出2乘以8等于几?

// 计算机底层乘法实现原理,效率最高
System.out.println(2 >> 3);

2、对两个整数变量的值进行互换?

  • 方式1:开发中常用的,使用中间变量
  • 方式2:不使用中间变量的,“和”实现
  • 方式3:面试中使用的,按位亦或 “^”
  • 方式4:一句话实现交换

方式1:开发中常用的,使用中间变量

 public class SwapDemo{
    public static  void main(String[] args) {
        int i = 10;
        int j = 20;

        int temp;
        temp = i;  //i = 10; j = 20; temp = 10;
        i = j;     //i = 20; j = 20; temp = 10;
        j = temp;  //i = 20; j = 10; temp = 10;

        System.out.println("i=" + i + ";j=" + j);
        // "i=20;j=10"
    }
}

方式2:不使用中间变量的,“和”实现

  • 这种方式不要用,如果两个整数的数值过大,会超出 int 范围,会强制转换,数据会变化
public class SwapDemo{
    public static  void main(String[] args) {
        int i = 10;
        int j = 20;

        i = i + j;   //i = 30; j = 20;
        j = i - j;   //i = 30; j = 10;
        i = i - j;   //i = 20; j = 10;

        System.out.println("i=" + i + ";j=" + j);
        // "i=20;j=10"
    }
}

方式3:面试中使用的,按位亦或 “^”

  • “^”的特点:某一数据对另一个数据”^”两次,该数本身不变
  • 面试题也可能描述为:请使用最高效的方法实现两个整数的值交换
public class SwapDemo{
    public static  void main(String[] args) {
        int i = 10;
        int j = 20;

        i = i ^ j;
        j = i ^ j;
        i = i ^ j;

        System.out.println("i=" + i + ";j=" + j);
        // "i=20;j=10"
    }
}

方式4:一句话实现交换

  • 了解即可,装逼必会[实际就是 方式2 的简化]
public class SwapDemo{
    public static  void main(String[] args) {
        int i = 10;
        int j = 20;

        j = ( i + j ) - ( i = j );

        System.out.println("i=" + i + ";j=" + j);
        // "i=20;j=10"
    }
}

三目运算符

格式:(条件表达式) ? 表达式1 : 表达式2;

  • 如果条件表达式为true,则执行表达式1
  • 如果条件表达式为false,则执行表达式2

表达式:具有一定语法规则的语句。

示例1:获取两个整数中的较大值

max = (x > y) ? x : y;

示例2:获取三个整数中的最大值

max = (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);


程序流程控制结构

顺序结构

【最基础的结构:自上而下执行】

选择结构

(1)、if语句

格式1:

if(条件表达式)
{
    执行语句;
}

示例1:

class IfDemo
{
    public static void main(String[] args)
    {
        int score = 70;
        if(score >= 60)
        {
            System.out.println("you pass the exam");
        }
    }
}

如果if语句没写大括号,if 就只能控制离它最近的单条语句
建议永远不要省略{ },这样具有更好的阅读性

格式2:

if(条件表达式)
{
    执行语句;
}
else
{
    执行语句;
}

示例2:

class IfDemo
{
    public static void main(String[] args)
    {
        int score = 70;
        if(score >= 60)
        {
            System.out.println("you win");
        }
        else
        {
            System.out.println("you fail");
        }
    }
}

P.S.
三元运算符就是 if else 语句的简写格式

简写格式什么时候可以使用呢?
    当 if else 运算之后,有一个具体的结果时,可以简写成三元运算符。但是,如果是 输出语句,就不可以使用三元运算符了

格式3:

if(条件表达式)
{
    执行语句;
}
else if(条件表达式)
{
    执行语句;
}
......
{
    执行语句;
}

示例3:

class IfDemo
{
    public static void main(String[] args)
    {
        int score = 70;
        if(score >= 90)
        {
            System.out.println("A");
        }
        else if(score >= 80)
        {
            System.out.println("B");
        }
        else if(score >= 70)
        {
            System.out.println("C");
        }
        else if(score >= 60)
        {
            System.out.println("D");
        }
        else 
        {
            System.out.println("E");
        }
    }
}

P.S.
if(条件表达式) 之后切记不可加分号”;“,否则无论表达式真假,都不执行任何语句
if(条件表达式); 相当于 if(条件表达式) {}; 其后的 { System.out.println(" "); }为局部代码块

局部代码块可以定义局部变量的生命周期,主要用来控制资源的释放,在移动端的开发中比较常见,因为移动端的资源是很宝贵的。

示例:

class IfDemo
{
    public static void main(String[] args)
    {
        if(true);
        {
            int m = 100;
            System.out.println("inner : " + m);
        }
        System.out.println("outter : " + m);
    }
}

运行结果:“错误: 找不到符号 m ”【outter 处的 m】

说明:变量m是局部变量,生命周期仅在局部代码块括号中,当代码执行到局部代码块右括号外,变量m便消失了。局部代码块外的代码当然也就访问不到变量m了。

if语句特点:

  • 1、每一种格式都是单条语句。
  • 2、第二种格式与三元运算符的区别:三元运算符运算完一定要有值出现。好处是:可以写在其他表达式中。
  • 3、条件表达式无论写成什么样子,只看最终的结构是否是true或者false。

(2)、switch语句

格式:

switch(表达式)
{
    case 取值1:
        执行语句;
        break;
    case 取值2:
        执行语句;
        break;
    ... ...
    default:
        执行语句;
        break;
}

switch语句特点

  • 1、switch语句选择的类型只有四种:byte short int char;JDK5.0之后支持 枚举,JDK7.0之后支持String【面试题】
  • 2、case与default没有顺序,先尝试第一个case,一次往下执行,没有匹配的case,就执行default
  • 3、结束switch语句的两种情况:①遇到break;②执行到switch语句结束 }
  • 4、如果没有匹配的case或default,没有对应的break,那么程序会继续执行下去,运行所有可以执行的语句,直到switch结束 }
  • 5、进入switch语句后,执行顺序:自上而下,先执行case,依次往下,没有符合的case,最后再执行default。即使 default 定义在所有case之前,执行顺序不变
  • 6、default可以没有

示例1:

class SwitchDemo
{
    public static void main(String[] args)
    {
        int score = 70;
        char grade = ' ';   
        switch(score / 10)
        {
            case 9:
                grade = 'A';
                break;
            case 8:
                grade = 'B';
                break;
            case 7:
                grade = 'C';
                break;
            case 6:
                grade = 'D';
                break;
            // case 0-5 时 执行同一条语句 grade='E';
            case 5:
            case 4:
            case 3:
            case 2:
            case 1:
            case 0:
                grade = 'E';
                break;
            default:
                break;
        }
        System.out.println(grade);
    }
}

示例2:case贯穿现象

class SwitchDemo
{
    public static void main(String[] args)
    {
        int a = 2;
        int b = 3;
        switch(a)
        {
            default:
                b++;
            case 3:
                b++;
            case 4:
                b++;
        }

        System.out.println(b);
    }
}

运行结果: 6

Java Basics 【Oriented Process】_第64张图片

总结:if和switch语句的应用:

if:

  • 1)、针对常量值的判断【多常量值时,使用 switch
  • 2)、针对一个范围判断
  • 3)、针对运算结果是 boolean 类型表达式的判断【执行语句返回的是值时,使用三目运算符

switch:

  • 1)、针对常量值的判断
  • 2)、值的个数通常是固定的

PS:针对常量值的判断,建议使用switch语句,因为switch语句会将具体的答案都加载进内存,效率相对较高


循环结构

关键词:while、do…while、for

(1)、while语句

格式:

初始化语句;
while(判断条件表达式)
{
    循环体语句;
    控制条件语句;
    //必须包含 控制条件语句,否则造成死循环
}

示例:

class WhileDemo
{
    public static void main(String[] args)
    {
        int x = 1;
        while(x < 3)
        {
            System.out.println("x = " + x);
            // 控制条件语句
            x++;
        }
    }
}

P.S.
一定要注意不要写while(x < 3); 相当于是 while(x < 3) {};,代表不执行任何语句遗失了控制条件语句,这个循环就成了一个死循环。

(2)、do…while语句

格式:

初始化语句;
do
{
    循环语句;
    控制条件语句;
    // 必须包含 控制条件语句,否则造成死循环
} while(判断条件语句);

示例:

class WhileDemo
{
    public static void main(String[] args)
    {
        int x = 1;
        do
        {
            System.out.println("x = " + x);
            // 控制条件语句
            x++;
        }while(x < 3);
    }
}

总结:对比while和do...while

  • do…while语句的特点:无论条件是否满足,循环体至少执行一次
  • while如果条件不满足,循环体一次都不会执行

(3)、for语句

格式:

for(初始化语句;判断条件语句;控制条件语句)
{
    循环语句;
}

**说明:**for里面的三个表达式运行的顺序,初始化语句只执行一次,判断条件语句为真就执行循环语句,然后再执行控制条件语句,接着执行判断条件语句,重复整个过程,直到条件不满足为止。

示例:1~10之间的偶数

class FoDemo
{
    public static void main(String[] args)
    {
        for(int i = 1; i <= 10; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println(i);
            }
        }
        /* 等价于:
         * for(int i = 2; i <= 10; i += 2) 
         * {
         *     System.out.println(i);
         * }
    }
}

示例:统计100以内所有3的倍数的个数–统计思想

class CountDemo
{
    public static void main(String[] args)
    {
        int count = 0;      
        for(int i = 0; i <= 100 ; i++)
        {
            if(i % 3 == 0)
            {
                count ++;
            }
        }
        System.out.println(count);
    }
}

>>>   33
『可以使用和求偶数一样的方式:for(int i = 3; i <= 100; i += 3){}』

示例:求N的阶乘N!–求积思想

import java.util.Scanner;

class MultiplyDemo
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);    
        int n = sc.nextInt();
        int q = 1;
        for(int i = 1; i <= n; i++)
        {
            q *= i;
        }
        System.out.println(q);
    }
}

P.S.
Scanner是键盘录入类,import java.util.Scanner;将类所在的包导入;使用Scanner sc = new Scanner(System.in);新建一个对象,sc.nextInt();获取键盘录入的一个int类型值

示例:求1-N的总和–求和思想

import java.util.Scanner

class SumDemo
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();   
        int sum = 0;
        for(int i = 1; i <= n; i++)
        {
            sum += i;
        }
        System.out.println(sum);        
    }
}

P.S.
for循环的初始化语句、控制条件语句可以有多个,之间使用,隔开


总结:for和while对比

  • 1、使用区别:如果初始化语句中的变量在循环之外还需使用的话,使用while;否则使用for,变量及早地从内存中消失,提高内存的利用率『变量的作用域』
  • 2、对于一个明确的范围,使用for;否则使用while
  • 3、在不影响阅读性的基础上,建议使用for,而不使用while

注意:死循环
- 1、控制条件语句必须有,正确控制变量
- 2、最简单的两种死循环:while(true)for(;;)

(4)、for嵌套

示例:输出正三角形

/*  需求:打印一下图形
 *      *
 *      **
 *      ***
 *      ****
 *  分析:  第1行,输出1个'*'
 *      第2行,输出2个'*'
 *      ......
 *      第n行,输出n个'*'
 *  实现:  用一个 i 控制第几行
 *      用一个 j 控制打印的数目
 *      j 的范围应该由 i 来控制
 *      每行输出完成之后,执行换行 System.out.println();
 *  编码:
 */
class StarDemo
{
    public static void main(String[] args)
    {
        for(int i = 1; i <= 4; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                System.out.print('*');
            }
            System.out.println();
        }
    }
}

示例:输出99乘法表

/*  需求:打印以下格式的99乘法表
 *      1×1=1
 *      1×2=2 2×2=4
 *      1×3=3 2×3=6 3×3=9
 *      1×4=4 2×4=8 3×4=12 4×4=16
 *      ......  
 *  分析:  第1行  1×1
 *      第2行  1×2 2×2
 *      第3行  1×3 2×3 3×3
 *      ......
 *      第n行  1×n 2×n 3×n ... n×n
 *  实现:   用 i 控制第几行
 *          用 j 控制该行有多少列
 *          j 的范围应该由 i 来控制
 *          每行输出完成之后,执行换行 System.out.println();
 *  编码:
 */
class TableDemo
{
    public static void main(String[] args)
    {
        for(int i = 1; i <= 9; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                System.out.print(j + "×" + i + "=" + i*j + "\t");
            }
            System.out.println();
        }
    }
}

> 1×1=1
  1×2=2 2×2=4
  1×3=3 2×3=6  3×3=9
  1×4=4 2×4=8  3×4=12 4×4=16
  1×5=5 2×5=10 3×5=15 4×5=20 5×5=25
  1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36
  1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49
  1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64
  1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81

跳转控制语句

break(中断)、continue(继续)、return(返回)
goto作为保留字,不可使用

(1)、break(中断)

使用场景:switch结构中、循环语句中的 if 判断,离开上述场景毫无意义!
如何使用:

  • ① 跳出单层循环:默认跳出最内层循环
  • ② 跳出多层循环(几乎不用):结合标签使用
outer:for(int i = 0; i < 3; i++)
{
    inner:for(int j = 0; j < 5; j++)
    {
        if(j == 2)
        {
            break outer;
            // break inner;
        }
    }   
}

(2)、continue(继续)

使用场景:循环语句中的 if 判断,离开此场景毫无意义!
如何使用:

  • ① 跳出单层循环:break跳出当前循环;continue跳出本次循环
  • ② 跳出多层循环(几乎不用):结合标签使用

(3)、return(返回)

使用场景:方法中,用于退出当前方法体,跳转到上层调用的方法;在main方法中的return用于结束程序

综合示例:写出程序的执行结果

class GotoDemo
{
    public static void main(String[] args)
    {
        for(int i = 1; i < 10; i++)
        {
            if(i % 2 == 0)
            {
                System.out.println("Exit");
                ____①;____
            }
            System.out.println(i);
        }
        System.out.println("Over");
    }
}

>>>   分别写出 ① 为breakcontinuereturn的结果
       ① 为 break
    >>>  1
         Exit
         Over

       ① 为 continue
    >>>  1
         Exit
         3
         Exit
         5
         Exit
         7
         Exit
         9
         Over

       ① 为 return
    >>>  1
         Exit

PS:以上三种语句应该放在局部代码块的最后,因为放于其后的代码永不执行

方法

定义

定义:类中完成特定功能的代码块。也称为函数,Java称为方法。

格式

修饰符 返回值类型 方法名(参数类型 形式参数1,参数类型 形式参数1,...)
{
    方法体;
    return 返回值;
}

>>>   "参数类型 形式参数1,参数类型 形式参数1,..."也就是参数列表

同一个代码块在出现两次以上考虑定义方法。

P.S.

  • 1、修饰符:目前只需要固定写成public static即可
  • 2、返回值类型:返回值的数据类型『数值类型、引用类型』
  • 3、方法名:标识符,方便调用
  • 4、参数:实际参数:实际参与运算的变量,形式参数:方法上用于接收实际参数值的变量
  • 5、参数类型:参数的数据类型
  • 6、方法体:完成特定功能的代码块
  • 7、return:结束方法,跳转到上层调用的方法
  • 8、返回值:return返回给调用者

如何定义方法

方法的定义:格式 + 两个明确『参数列表、返回值类型』

方法的特点:

  • 1、定义方法可以将功能代码进行封装
  • 2、便于对该功能进行复用,提高了代码的复用性
  • 3、方法不调用不执行
  • 4、方法之间是平级关系,不可以嵌套定义
  • 5、方法定义时,参数类表使用”,”分割
  • 6、方法调用时,不传递参数类型
  • 7、方法有明确的返回值

注意:

  • 1、对于方法没有具体返回值的情况,返回值类型使用关键字void,该函数中的return语句可以省略不写,或者写上return;
  • 2、函数中只能调用函数,不可以在函数内部定义函数。否则,编译时期就会报错。
  • 3、定义函数时,函数的结果应该返回给调用者,交由调用者处理。

对于第3点,请对比以下完成两个数值和的代码块:

public static void sum(int a,int b)
{
    System.out.println(a+b);
}
public static int sum(int a,int b)
{
    return a + b;
}

虽说两种都可以执行出正确的数据,下面的代码比较好,因为调用者只需要获取两数相加的结果,而不需要方法做打印的操作!

按照方法定义的要求:格式 + 两个明确,完成以下示例:

示例1:输出n列m行的”*”方法

/*  需求:输出n行m列的 * 
 *      例如:当n=3,m=4时
 *      ****
 *      ****
 *      ****
 *  分析:n代表一共几行,m代表一行打印多少个
 *        方法的需求中强调将其直接打印出来
 *        可以明确返回值类型是void,
 *        也就是说return可以省略不写或者使用return;
 *        n行m列,所以参数列表应该是(int n,int m)
 *
 *  综上,格式为:
 *  public static void PrintStar(int n,int m)
 *  {
 *      //return;
 *  }
 *
 *  编码实现
 */
import java.util.Scanner;

class StarDemo
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        System.out.println("Please input an integer(n):");
        int n = sc.nextInt();
        System.out.println("Please input an integer(m):");
        int m = sc.nextInt();
        PrintStar(n,m);
    }

    public static void PrintStar(int n,int m)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

示例2:输出nn乘法表(1~9)

/*  需求:输出nn乘法表,且n在1-9之间
 *        借鉴之前的99乘法表
 *      1×1=1
 *      1×2=2 2×2=4
 *      1×3=3 2×3=6 3×3=9
 *      ... ...
 *  分析:根据需求中的方法的功能是输出,明确返回值类型是void,
 *        返回值是return; 或者省略
 *        明确是nn乘法表。所以方法的参数是一个int类型的n 
 *        第一个n确认的是行数,第二个n确认改行打印的程式的个数
 *  综上,格式是:
 *  public static void PrintTable(int n)
 *  {
 *      //return;
 *  }
 *  编码实现:
 */
import java.util.Scanner;

class TableDemo
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        System.out.println("Please inoput an integer:");
        int n = sc.nextInt();
        PrintTable(n);
    }

    public static void PrintTable(int n)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= i; j++)
            {
                System.out.print(j + "*" + i + "=" + j*i +"\t");
            }
            System.out.println();
        }
    }
}

示例3:获取两个整数中的最大数

/*  需求:获取两个整数中的最大数;
 *  分析:明确参数列表是两个int类型的参数
 *        返回值类型也是int类型
 *        根据功能需求是获取,也就是需要把方法处理后结果返还给调用者
 * 综上:格式为:
 *  public static int max(int a,int b)
 *  {
 *      return max;
 *  }
 *  编码实现:
 */
class MaxDemo
{
    public static void main(String[] args)
    {
        int a = 12;
        int b = -1;
        int max = max(a, b);
        System.out.println(max);
    }

    public static int max(int a,int b)
    {
        return (a > b) ? a : b;
    }
}

练习:判断两个整数是否相等
练习:获取两个整数的和

示例4:获取三个整数中的最大数

/*
 *  需求分析参考上述示例3
 */
class MaxDemo
{
    public static void main(String[] args)
    {
        int a = 12;
        int b = -1;
        int c = 23;
        int max = max(a, b, c);
        System.out.println(max);
    }

    public static int max(int a,int b,int c)
    {
        return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
    }
}

对比示例3、4可以发现两个方法的功能相同,方法名相同,只是参数列表不同,具有类似功能的方法应该定义在相同的类中完成封装。这就引出了Java中的方法重载(OverLoad)。

方法重载(OverLoad)

方法重载(OverLoad):

  • 同一类中,完成同样功能的方法,为了见名知意,允许具有相同的方法名,不同的参数列表,这种现象就叫做方法重载(OverLoad)。
  • 不同的参数列表包含两种含义:参数的数据类型不同、参数的个数不同。
  • 从定义中可以看到,重载只和参数列表有关,与方法的返回值无关。

调用时候,JVM(Java Virtual Machine)根据参数列表的不同来区分同名方法

示例:实现获取最大值的类

class MaxDemo
{
    public static void main(String[] args)
    {
        int a = 12;
        int b = -1;
        int c = 23;
        int max = max(a, b, c); 
        System.out.println(max);
    }

    public static int max(int a,int b,int c)
    {
        //return (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
        return max(max(a, b), c);
    }

    public static int max(int a,int b)
    {
        return (a > b) ? a : b;
    }

    public static float max(float a,float b)
    {
        return (a > b) ? a : b;
    }
}

引用数据类型之一:数组(『一维数组』)

定义

定义:数组是存储同一数据类型的多个元素的集合(容器)

格式

  • 格式1:数据类型[] 数组名 (推荐方式)
  • 格式2:数据类型 数组名[] (C#已无)

初始化

数组初始化:为数组中的元素分配内存空间并为其赋值,Java中的数组必须先进行初始化才可以使用

  • 1、动态初始化:只指定数组的长度(内存空间),由系统为数组分配初始值(0\null)
  • 格式:数据类型[] 数组名 = new 数据类型[数组长度]
  • 案例:int[] arr = new int[9];
  • 2、静态初始化:只指定每个元素的值,由系统为其指定长度(内存空间)
  • 格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3…}
  • 案例:int[] arr = new int[]{1,2,3,4,5,6,7,8,9};

new 为数组申请内存空间
数组的下标是从 0 开始,、最大值 为:length-1

堆栈的特点

Java中的内存分配:

  • Java中程序在运行时,需要在内存中为其分配空间,为了提高效率,将内存空间进行了不同的划分,让每块区域都有自己特定的数据处理方式和内存管理方法。

大致可以分为以下5种:

  • 1、栈:存储局部变量,当变量所属的作用域一旦结束,所占空间会自动释放
  • 2、堆:通常new出来的数组或对象都放置在堆内存中
  • 3、方法区:class文件内容
  • 4、本地方法区:与系统相关
  • 5、寄存器:共CPU使用

局部变量:在方法声明中或方法定义上的变量。

示例代码1:

class ArrayDemo
{
    public static void main(String[] args)
    {
        int[] arr = new int[3];
        System.out.println(arr);
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);
    }
}

>>>   [I@659e0bfd  // 地址值:"[" 代表是一位数组;"I" 代表是int类型;
                   // "@"之后的是映射的十六进制地址值
      0
      0
      0    // 打印的三个元素值,是由JVM系统给定的初始值

内存图解:

Java Basics 【Oriented Process】_第65张图片

堆内存的特点:


  • A:每一个new出来的对象都有地址值
  • B:每一个变量都有默认值
  • C:使用完成(栈中没有指向它的变量)就成了垃圾,但并没有马上回收。在垃圾回收器空闲时回收。
    注意:C++内类型的析构函数就是为了释放空间,但在Java中是自动进行的

基本数据类型默认值:

- byte、short、int、long默认是 0
- float、double默认是 0.0
- char 默认是 ‘、u0000’ - 空字符
- boolean 默认是 false
- 引用数据类型 默认是 null


栈内存的特点
数据用完就释放掉(超出作用域”}“)

示例代码2:

{
    int a = 10;
    System.out.println(a)   ;
}  //  在这里 a 已经被释放了,之后再对 a 访问造成 未定义的错误

示例代码2的基础之上,进行以下的操作:

arr[0] = 100;
arr[1] = 100;

内存图解:

Java Basics 【Oriented Process】_第66张图片

示例代码3:

class ArrayDemo
{
    public static void main(String[] args)
    {
        int[] arr = new int[3];
        int[] ar = arr;
        arr[0] = 100;
        arr[1] = 100;
        ar[0] = 10;
        ar[1] = 20;
        ar[2] = 30;

        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);
    }
}

>>>   10
      20
      30

内存图解:

Java Basics 【Oriented Process】_第67张图片


静态初始化:指定元素的值,由系统分配内存长度

格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2…};

简写格式是:数据类型[] 数组名 = {元素1, 元素2…};

int[] arr = new int[]{1, 2, 3};
// int[] arr = {1, 2, 3};

内存图解:

Java Basics 【Oriented Process】_第68张图片


切记:不可同时对数组进行动态和静态初始化,即:int[] arr = new int[3]{1, 2, 3}; 是不合法的。

数组常见问题

Exception:异常

  • 1、识别 现象
  • 2、分析 原因
  • 3、如何 改进
(1)、ArrayIndexOutOfBoundsException:数组索引(下标)越界异常
原因:数组的下标不在 [0,length-1]之间
改进:对数组进行访问时,时刻注意索引越界异常
(2)、NullPointerException:空指针异常
原因:数组不再指向堆内存,却还使用数组名访问元素;譬如: int[] arr = null;
改进:对数组进行访问时,时刻注意数组是否还可正常访问

数组常见操作

(1)、遍历

for(int i = 0; i < array.length; i++)
{
    // 操作
}

>>>   数组名.length 是获取数组的长度 int类型值

(2)、获取最值

int max = array[0];
// 获取数组中的第一个元素值,作为参照
// 不可以使用非数组中元素作为参照,比如说:0

// 遍历之后的 [1,length-1] 元素,与参照对比
//      如果大于参照,就把他的值赋给参照
//      如果小于参照,则继续下一个元素的比较
for(int i = 1; i < array.length; i++)
{
    if(array[i] > max)
    {
        max = array[i];
    }
}
// 通过遍历全部元素之后,获得最大值
System.out.println(max); 

>>>   数组名.length 是获取数组的长度 int类型值

PS:最小值的问题与此类似,请自行分析!

(3)、逆序(Reverse)

所谓的数组逆序,就是倒序;譬如{1, 2, 3}逆序为{3, 2, 1}

第1种实现:定义新的数组

// 定义新的同类型数组(使用元数组的长度动态初始化定义)
int[] rArray = new int[array.length]; 
// 遍历数组所有元素,实现倒序
for(int i = 0; i < array.length; i++)
{
    rArray[array.length-1-i] = array[i];
}
// 实现比较简单:但是耗费了额外的内存空间。好处是没有改变原来数组

第2种实现:使用原数组

// 以中间元素为基准,将数组元素进行交换
// 第一个和倒数第一个,第二个和倒数第二个,以此类推
for(int i = 0; i < (array.length-1) / 2; i++)
{
    // 实现两个正整数的交换-四种方式
    // 第一种方式:使用中间变量
    int t = array[i];
    array[i] = array[array.length-1-i];
    array[array.length-1-i] = t;
}
// 使用while实现:从两头向中间靠近,到达中间之后就停止
int start  = 0;
int end = array.length-1;
while(start != end)
{
    int t = array[start];
    array[start] = array[end];
    array[end] = t;
    // 两头向中间靠近
    start++;
    end--; 
}

(4)、数组查表法:以索引获取指定元素

方法实现:明确参数列表是(int[] arr,int index);返回值类型 int类型

public static int getValue(int[] arr, int index)
{
    if(index >= 0 && index < arr.length)
    {
        return arr[index];
    }
    else
    {
        // 暂时使用 -1 代表ArrayIndexOutOfBoundsException异常
        return -1;
    }
}

(5)、基本查找:查找指定元素在数组中第一次出现的位置

方法实现:明确参数列表是(int[] arr,int value);返回值类型 int类型

public static int getIndex(int[] arr, int value)
{
    for(int i = 0; i < arr.length; i++)
    {
        if(arr[i] == value)
        {
            return i;
        }
    }
    // -1 表示数组中不存在该元素
    return -1;
}

上述两个部分代码看似实现了功能,但是不具有很好的阅读性:

public static int getIndex(int[] arr, int value)
{
    // -1 表示数组中不存在该元素
    int index = -1;
    for(int i = 0; i < arr.length; i++)
    {
        if(arr[i] == value)
        {
            index = i;
            // 找到第一个元素之后,应该结束当前的循环
            break;
        }
    }

    return index;
}

参照getIndex,请自行修改方法getValue,使其具有更好的阅读性。

二维数组

定义

定义:元素是一维数组的数组

格式

    格式1:数据类型[][] 数组名 = new 数据类型[m][n];由m个长度为n的一维数组组成的数组
数据类型[] 数组名[] = new 数据类型[m][n];
数据类型 数组名[][] = new 数据类型[m][n];

示例1:分析以下的代码片段:

int[] x, y[];   // x是一维数组,y是二维数组:拆开定义就显而易见了
// x是一维数组,y是二维数组:拆开定义就显而易见了
int[] x;
int[] y[];
class ArrayDemo
{
    public static void main(String[] args)
    {
        int[][] arr = new int[3][2];
        System.out.println(arr);
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);
        System.out.println(arr[1][0]);
        System.out.println(arr[1][2]);
    }
}

>>>   [[I@659e0bfd  // "[[" 代表是二维数组,"I" 代表是int类型,
                    // "@"之后的是映射的内存地址
      [I@2a139a55   // "[" 代表的是一维数组,其他的同上
      [I@15db9742
      [I@6d06d69c
      0      // 堆内存中,int类型的默认值是 0
      0

内存图解:

Java Basics 【Oriented Process】_第69张图片


  • 格式2:数据类型[][] 数组名 = new 数据类型[m][];由m个一维数组组成的二维数组,以为数组的长度动态给出

示例2:分析以下的代码片段:

class ArrayDemo
{
    public static void main(String[] args)
    {
        int[][] arr = new int[3][];
        System.out.println(arr);
        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);

        arr[0] = new int[2];
        arr[1] = new int[3];
        arr[2] = new int[1];

        System.out.println(arr[0]);
        System.out.println(arr[1]);
        System.out.println(arr[2]);

        System.out.println(arr[1][0]);
        System.out.println(arr[1][2]);

        arr[1][0] = 100;
        arr[1][2] = 200;

        System.out.println(arr[1][0]);
        System.out.println(arr[1][2]);
    }
}

>>>   [[I@659e0bfd  // "[[" 代表是二维数组,"I" 代表是int类型,
                    // "@"之后的是映射的内存地址
      null   // 堆内存中,一维数组是引用类型,默认值是 null
      null
      null
      0      // 堆内存中,int类型的默认值是 0
      0
      [I@2a139a55   // "[" 代表的是一维数组,其他的同上
      [I@15db9742
      [I@6d06d69c
      100    // 完成了数组元素的赋值
      200

内存图解

Java Basics 【Oriented Process】_第70张图片
Java Basics 【Oriented Process】_第71张图片


  • 格式3:数据类型[][] 数组名 = new 数据类型[][]{{,..},{,..}…}
  • 简化格式是:数据类型[][] 数组名 = {{,..},{,..}...}

示例3:分析以下代码片段:

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

        System.out.println(arr[0][1]);
        System.out.println(arr[2][0]);
    }
}

>>>   [[I@659e0bfd
      [I@2a139a55
      [I@15db9742
      [I@6d06d69c
      2
      6

内存图解

Java Basics 【Oriented Process】_第72张图片

初始化

动态初始化:『只指定数组的长度,具体的值由JVM虚拟机默认初始化』格式1、格式2
动态初始化:『只给出所有元素的值,数组的长度由JVM虚拟机给出』格式3

二维数组操作及应用

(1)、遍历

class ArrayDemo 
{
    public static void main(String[] args)
    {
        int[][] arr = {{1, 2, 3}, {4, 5}, {6}};
        for(int m = 0; m < arr.length; m++)
        {
            for(int n = 0; n < arr[m].length; n++)
            {
                System.out.print(arr[m][n] + "\t");
            }
            System.out.println();
        }
    }
}

>>>   1    2   3
      4    5
      6

(2)、求和(求和思想+遍历)

class ArrayDemo 
{
    public static void main(String[] args)
    {
        int[][] arr = {{1, 2, 3}, {4, 5}, {6}};
        int sum = 0;
        for(int m = 0; m < arr.length; m++)
        {
            for(int n = 0; n < arr[m].length; n++)
            {
                sum += arr[m][n];
            }
        }
        System.out.println(sum);
    }
}

>>>   21

(3)、杨辉三角性-综合案例

/*
 *  需求:根据用户输入的行号,输出杨辉三角性
 *      譬如:输入行号为 5 
 *      输出:  1
 *          1 1
 *          1 2 1
 *          1 3 3 1
 *          1 4 6 4 1
 *          1 5 10 10 5 1
 *
 *  分析:使用二维数组作为数据结构
 *      输出的行数是输入的行号+1
 *      每行的列数和该行行号相同
 *      第一列的数字均为1,对角线的数字均为1
 *      从第三行开始,除掉第一数字1、最后一个数字1;
 *        从第二个数字开始,该数字的值等于上一行的
 *        该列数字和它前一列的数字之和
 *  
 *  实现:
 *      定义一个二维数组:int[][] arr = new int[n+1][]
 *      初始化二维数组中的每一个一维数组的值
 *          1、定义一个直角三角形的二维数组,其中每个一维数组的长度
 *              等于二维数组下标+1,同时将一维数组的第一列和
 *              对角线上的数字初始化为 1
 *              for(int i = 0; i < arr.length; i++)
 *              {
 *                  arr[i] = new int[i + 1];
 *                  arr[i][0] = 1;
 *                  arr[i][i] = 1;
 *              }
 *
 *          2、从第三行开始每行的第二个元素到对角线之前的那个元素,
 *               都等于上一行同列的元素以及前列的元素之和
 *              for(int i = 2; i < arr.length; i++)
 *              {
 *                  for(int j = 1; j < arr[i].length-1; j++)
 *                  {
 *                      arr[i][j] = arr[i-1][j] + arr[i-1][j-2];
 *                  }
 *              }
 *
 *          3、遍历打印二维数组
 *              for(int i = 0; i < arr.length; i++)
 *              {
 *                  for(int j = 0; j < arr[i].length; j++)
 *                  {
 *                      System.out.print(arr[i][j] + "  ");
 *                  }
 *                  System.out.println();
 *              }
 */
import java.util.Scanner;

/**
*   这是一个实现打印杨辉三角性的类
*   @author JoianSun
*/
class TriangleDemo
{
    public static void main(String[] args)
    {
        // 定义键盘录入对象,接收用户录入的行数
        Scanner sc = new Scanner(System.in);
        System.out.println("Please input a number(n > 0):");

        // 接收用户输入的行数
        int line = sc.nextInt();

        // 判断用户输入的行数是否合法,如果不合法,立即结束程序
        if(line < 0)
        {
            System.out.println("Please input a postive integer!");
            return;
        }       

        // 用户输入的line合法的话,继续实现
        // 1、实现数据结构的初始化
        int[][] arr = new int[line + 1][];

        /* 2、定义二维数组中每个一维数组的长度
         *  (一维数组的长度等于该一维数组在二维数组中的下标+1)
         *  并对每个一维数组第一个元素和对角线上
         *  (也就是最后一个元素)的元素进行 1 赋值
         */
        for(int i = 0; i < arr.length; i++)
        {
            // 定义一维数组的长度
            arr[i] = new int[i + 1];

            // 首尾元素赋值为 1
            arr[i][0] = 1;
            arr[i][i] = 1;
        }

        // 3、将一维数组中的非首尾元素按规律赋值
        for(int i = 2; i < arr.length; i++)
        {
            for(int j = 1; j < arr[i].length-1; j++)
            {
                arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
            }
        }

        // 4、遍历打印二维数组
        for(int i = 0; i < arr.length; i++)
        {
            for(int j = 0; j < arr[i].length; j++)
            {
                System.out.print(arr[i][j] + "  ");
            }
            System.out.println();
        }
    }
}

思考题

Java中的参数传递问题

class Demo
{
    public static void main(String[] args)
    {
        int a = 10;
        int b = 20;
        System.out.println("a=" + a + ",b=" + b);
        change(a, b);
        System.out.println("a=" + a + ",b=" + b);
        int[] arr = {1, 2, 3, 4, 5};
        change(arr);
        System.out.println(arr[1]);
    }

    public static void change(int a, int b)
    {
        System.out.println("a=" + a + ",b=" + b);
        a = b;
        b = a + b;
        System.out.println("a=" + a + ",b=" + b);
    }

    public static void change(int[] arr)
    {
        for(int i = 0; i < arr.length; i++)
        {
            if(arr[i] % 2 == 0)
            {
                arr[i] *= 2;
            }
        }
    }
}

>>>   a=10,b=20  // main方法中,打印a、b的值
      a=10,b=20  // change方法中,打印a、b的值
      a=20,b=40  // change方法中,在将a=b; b=a+b;执行完毕后的打印
      a=10,b=20  
    /* main方法中,打印a、b的值,值没变的原因是:change方法上形式参数
        接受了a、b值,只是把main方法中a、b的值传给了change方法
        中的a、b,并在change方法内部做了操作,但是在main方法中
        并没有对a、b做任何的操作,所以并没有改变main方法中的a、b值 */

      4   
    /* main方法中的数组下标为1的元素的值是2,将数组的地址值传递到change
        方法中,实际上相当于两个不同方法中的arr指向了同一块堆内存区域,
        所以在change中改变了的数组元素的值,会被main方法中的数组
        同样引用到,所以arr[1]的值被改变  */

P.S.
Java中只有一种参数传递的方式:值传递
- 基本数据类型:传递的是数值的大小『形式参数和实际参数互不影响』
- 引用数据类型:传递的是 地址值 『形式参数改变直接作用到实际参数』

综合案例:加密问题

/*
 *  1、问题描述:
 *      某个公司采用公用电话传递数据信息,数据是小于8位的整数,为了确保安全,
 *      在传递过程中需要加密。
 *      加密规则如下:首先将数据倒序,然后将每位数字都加上5,再用和
 *          除以10的余数代替该数字,最后将第一位和最后一位数字交换。
 *      请任意给定一个小于8位的整数,然后,把加密后的结果在控制台打印出来。 
 *
 *  2、获取需求:
 *      实现将用户输入的小于8位正整数字,按照给定的规则加密,并打印出来
 *
 *  3、分析:
 *      (1)获取给定的不小于8位的整数
 *      
 *      (2)分析主要规定的规则:
 *          a、原始数据倒序
 *          b、将每一个数字加上5
 *          c、和与10取余代替当前数字
 *          d、首尾数字交换
 *  
 *      (3)将所得加密后的数字打印
 *
 *  4、实现:
 *      数据结构:采用一维数组,长度为8
 *      
 *      规则实现:
 *      a、原始数据倒序
 *          拆数:获取各个位置上的数字
 *              拆数过程中从个位数字开始获取,存储从数组的0索引开始,
 *              已经实现了数组的逆置
 *          逆置数组(reverse函数)
 *
 *      b、将每一个数字加上5
 *          一维数组的遍历:for循环
 *          num += 5;
 *
 *      c、和与10取余代替当前数字
 *          num %= 10;          
 *      
 *      d、首尾数字交换
 *          实现正整数交换的四种方式
 *          (1)中间变量temp
 *          (2)不借助中间变量(+)
 *          (3)使用按位异或的特点:
 *              某一数据和同一数据异或两次,数据本身不变
 *          (4)一句话实现:
 *              b = (a+b) -(a=b); 可读性很差且代码不规范
 *  
 *  5、编码
 */
import java.util.Scanner;

public class JiaMiDemo
{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入原始数据:");
        // 1、获取原始数据
        int data = sc.nextInt();

/*
        // 2、定义数据结构:一维数组
        int[] dataArray = new int[8];
        int count = 0;   // 记录索引位置(数组的实际长度)

        // 3、原始数据倒序
        //      拆数:获取各个位置上的数字
        //          拆数过程中从个位数字开始获取,存储从数组的0索引开始,
        //          已经实现了数组的逆置
        //      逆置数组(reverse函数)

        while(data!=0)
        {
            dataArray[count] = data % 10;
            count ++;
            data /= 10;
        }
*/

        // 拆数函数实现2、3
        int[] dataArray = chaiShu(data);

        // 获取数组的实际长度
        int count = dataArray[8];

        /* 4、将每一个数字加上5
         *      一维数组的遍历:for循环
         *  5、和与10取余代替当前数字
         */
        for(int i=0;i5;
            dataArray[i] %= 10;
        }

        // 6、首尾数字交换
        int temp = dataArray[0];
        dataArray[0] = dataArray[count-1];
        dataArray[count-1] = temp;

        // 7、实现加密数据的输出
        String jiami="";
        for (int i=0;i"加密后的数据是:\n"+ jiami);
    }

    /* 拆数函数:获取各个位置上的数字
     *  拆数过程中从个位数字开始获取,存储从数组的0索引开始,
     *  已经实现了数组的逆置
     */
    public static int[] chaiShu(int num)
    {
        int[] arr = new int[9];
        int index = 0;
        while(num!=0)
        {
            arr[index++]=num%10;
            num/=10;
        }
        // 最后一位存储数组的实际长度
        arr[8] = index;
        return arr;
    }
}

你可能感兴趣的:(Java笔记)