JavaSE

JavaSE

1、Java语言概述


1.1、基础常识

计算机重要组成部分:硬件与软件

硬件

CPU、内存、存储设备、输入设备、输出设备、通信设备

  • CPU(Central Processing Unit,中央处理器)
    • 人靠大脑思考,电脑靠CPU来运算、控制
  • 硬盘(Hard Disk Drive)
    • 计算机最主要的存储设备,容量大,断电数据不丢失
    • 分类:机械硬盘(HDD)固态硬盘(SSD)以及混合硬盘(SSHD)
    • 固态硬盘在开机速度和程序加载速度远远高于机械硬盘
  • 内存(Memory)
    • 负责硬盘上的数据与CPU之间数据交换处理
    • 保存从硬盘读取的数据,提供给CPU使用;保存CPU的一些临时执行结果,以便CPU下次使用或保存到硬盘
    • 断电后数据丢失(断电即失)
软件

软件:即一系列按照特定顺序组织的计算机数据和指令的集合,可分为系统软件应用软件

系统软件:windows、mac os、linux、unix、android、ios

应用软件:word、微信、饿了么、淘宝、高德地图、百度网盘……

人机交互方式

  • 图形化界面(Graphical User Interface GUI)该方式简单直观,使用者易于接受,容易上手操作

  • 命令行方式(Command Line Interface CLI):需要在控制台输入一些特定的指令,让计算机完成一些操作。较为麻烦,需要记住一些命令

常用DOC命令

  • dir: 列出当前目录下的文件以及文件夹
  • e::快速切换到 E 盘
  • md: 创建目录
  • rd: 删除目录
  • cd: 进入指定目录
  • cd …: 退回到上一级目录
  • cd \: 退回到根目录
  • del: 删除文件
  • exit: 退出 dos 命令行
  • 常用快捷键
    • ← →:移动光标
    • ↑ ↓:调阅历史操作命令
    • Delete和Backspace:删除字符
    • cls:清屏
    • exit:退出终端

1.2、初识Java

应用程序 = 数据结构 + 算法

计算机语言发展迭代史

  • 第一代:机器语言,指令以二进制代码形式存在(打孔纸带)
  • 第二代:汇编语言,使用助记符表示一条机器指令(add、sub、mov)
  • 第三代:高级语言
    • 面向过程: C、Pascal、Fortran
    • 面向过程/面向对象:C++
    • 面向对象:Java、JavaScript、Python

不管是什么语言,最后都要向机器语言靠近,因为CPU只认识0和1

语言排行榜

Java是什么?

Java是SUN(Stanford University Network,斯坦福大学网络公司 ) 1995年推出的一门高级编程语言

随着互联网的快速发展,同时也随着Java技术在Web方面的不断成熟,已经成为Web应用程序的首选开发语言

Java语言版本迭代

发行版本发行时间备注
Java 1.01996.01.23Sun公司发布了Java的第一个开发工具包
Java 1.11997.02.19JavaOne会议召开,创当时全球同类会议规模之最
Java 1.21998.12.08Java拆分成:J2SE(标准版)、J2EE(企业版)、J2ME(小型版)
Java 1.32000.05.08
Java1.42004.02.06
Java 5.02004.09.30①版本号从1.4直接更新至5.0;②平台更名为JavaSE、JavaEE、JavaME
Java 6.02006.12.112009.04.20 Oracle宣布收购SUN公司
2009.04.20Oracle公司收购SUN,交易价格74亿美元
Java 7.02011.07.02
Java 8.02014.03.18此版本是继Java 5.0以来变化最大的版本。是长期支持版本(LTS)
Java 9.02017.09.22①此版本开始,每半年更新一次;②Java 9.0开始不再支持windows 32位系统
Java 10.02018.03.21
Java 11.02018.09.25JDK安装包取消独立JRE安装包,是长期支持版本(LTS)
Java 12.02019.03.19
Java17.02021.09发布Java 17.0,版本号也称为21.9,是长期支持版本。
Java19.02022.09发布Java19.0,版本号也称为22.9

应用领域

  • 企业级应用领域(JavaEE后台):开发企业级的应用程序、各种类型的网站
  • 移动应用领域(集成Android平台):Java在Android端是主要的开发语言,占有重要地位
  • 大数据分析、人工智能领域:流行的大数据框架,如Hadoop、Flink都是用Java编写的

语言特点

  • 面向对象性

    • 两个要素:类、对象
    • 三个特征:封装、继承、多态
  • 健壮(安全)性

    • 吸收了C/C++语言的优点,但去掉了其影响程序健壮性的部分(如指针、内存的申请与释放等),提供了一个相对安全的内存管理和访问机制
    • 自动的垃圾回收机制,仍会出现内存溢出、内存泄露问题
  • 跨平台性

    • Write once,Run Anywhere一次编译,到处运行

    • 一切功劳都归功于JVM (Java Virtual Machine)

Java两种核心机制

  • Java虚拟机 (Java Virtal Machine)
  • 垃圾收集机制 (Garbage Collection)

JDK、JRE、JVM三者之间的关系

  • JDK:Java Development Kit(开发者工具)
  • JRE:Java RunTime Environment(运行时环境)
  • JVM:Java Virtual Machine(Java虚拟机)

JDK下载与安装

下载地址

注:安装路径尽量不要包含中文或者空格等特殊符号

path环境变量的配置

环境变量

path环境变量:windows操作系统执行命令时所要搜寻的路径

为什么要配置path环境变量?

希望java的开发工具(javac.exe、java.exe)在任何文件的执行路径下都可执行成功!

如何配置?

1.3、Java三大版本

  • JavaSE:标准版(桌面程序、控制台开发 )
  • JavaME:嵌入式开发(手机、小家电)
  • JavaEE:企业级开发(web端、服务器开发)

1.4、第一个Java程序

我的第一个Java程序——HelloWorld

  1. 编写源文件

    创建java源文件,文件名为:HelloWorld.java

    public class HelloWorld{
        public static void main(String[] args){
            System.out.println("Hello World!!!");
        }
    }
    
  2. 编译源文件

    # javac 源文件名.java
    javac HelloWorld.java
    
  3. 运行.class文件

    # java 类名
    java HelloWorld
    

注:在一个java源文件中可以包含多个class。但是,只能有一个类声明为public的,并且要求声明为public的类应与文件名一致,否则编译失败!

编译之后,会生成一个或多个字节码文件,字节码文件的文件名与java源文件中的类名相同

1.5、注释与API文档

注释(Comment):用于注解说明解释程序的文字就是注释

分为三类

  • 单行注释: //
  • 多行注释: /* */
  • 文档注释(java特有) : /** */

作用

  • 对编写的程序进行解释说明,增强代码可读性,便于协作开发
  • 便于调试自己所写的代码

特点:对于单行和多行注释,注释的文字不参与编译,换而言之,编译以后生成的以.class结尾的字节码文件中不包含注释掉的信息

对于文档注释,注释的内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件形式体现该程序的说明文档

/**
 * @author zhang    作者
 * @version 1.0     版本号
 * @since   1.8     需要使用的jdk版本
 */

/**
     *
     * @param name      参数名
     * @param pwd
     * @return      返回值
     * @throws Exception    异常抛出情况
 */
public boolean login(String name,String pwd) throws Exception{
    return true;
}

Java API文档:

API:(Application Programming Interface,应用程序编程接口)是 Java 提供的基本编程接口,通常习惯上将语言提供的类库,都称为API

API文档:针对于提供的类库如何使用所提供的一个说明书,类似于汉字中的《新华字典》

Java API文档

2、变量与数据类型


2.1、关键字和保留字

关键字(keyword)定义和特点

定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词)

特点:关键字中所有字母都为小写

官方地址

Java保留字(reserved word):现有Java版本尚未使用,但以后版本可能会作为关键使用功能用。自己命名标识符时要避免使用这些保留字,goto 、const

2.2、标识符

标识符(Identifier):Java 对各种变量方法等要素命名时使用的字符序列称为标识符

注:凡是自己可以起名字的地方都叫标识符

定义合法标识符规则:字下美元其后数,不可使用关键字或保留字,但可以包含关键字和保留字,不能包含空格

Java中的名称命名规范

注:在起名称时,为了提高代码可读性,要尽量起的有意义 见名知意

java采用unicode字符集,因此标识符也可以使用汉字声明,但是不推荐使用

阿里巴巴Java开发手册

2.3、变量

变量的概念
  • 内存中的一个存储区域
  • 该区域的数据可以在同一类型范围内不断变化
  • 变量是程序中最基本的存储单元。包含变量类型、变量名和存储的值

变量的作用:用于在内存中保存数据

注:

  • Java中每个变量必须先声明,后使用
  • 使用变量名来访问这块区域的数据
  • 变量的作用域:其定义所在的一对{ }
  • 变量只有在其作用域内才有效,同一个作用域内,不能定义重名的变量

变量的分类
按数据类型划分

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

Java各整数类型有固定的表数范围和字段长度,不受具体OS的影响,以保证java程序的可移植性

整型

java的整型常量默认为 int 型,声明long型常量后面须加L

java程序中变量通常声明为 int 型,除非不足以表示较大的数,才使用long

byte b =  110;
short s = 256;
int number = 10;
long count = 1354684542564L;

注:bit:计算机中的最小存储单位。byte:计算机中的基本存储单元

浮点型

与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体操作系统的影响

float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求

double:双精度,精度是float的两倍。通常采用此类型

Java的浮点型常量默认为double型,声明float型常量,后面须加加‘f’或‘F’

float f = 15896456245F;
double d = 6.19;

字符型

char 型数据用来表示通常意义上“字符”(1字符 = 2字节)

Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符

// 表示方式一:声明一个字符
char bigLetter = 'A';
char smallLetter = 'a';
char chineseCharacter = '林';
// 表示方式二:转义字符
char c1 = '\n';
char c2 = '\t';
// 表示方式三:Unicode值
char c3 = '\u0031';

注:char类型是可以进行运算的。因为它有对应的Unicode码

布尔类型

boolean 类型用来判断逻辑条件,一般用于程序流程控制:

if条件控制语句;

while循环控制语句;

do-while循环控制语句;

for循环控制语句;

注:boolean类型数据只允许取值true和false,无null

按声明位置的不同划分

在方法体外,类里面声明的变量称为成员变量

在方法体内部声明的变量称为局部变量

2.4、数据类型

强类型语言

  • 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用

弱类型语言

  • 弱类型语言是一种弱类型定义的语言,某一个变量被定义类型,该变量可以根据环境变化自动进行转换,不需要经过显性强制转换。弱类型语言包括vb 、PHP、javascript等语言

强类型语言和弱类型语言区别

  • 无论是强类型语言还是弱类型语言,判别的根本是是否会隐性的进行语言类型转变。强类型语言在速度上略逊于弱类型语言,但是强类型定义语言带来的严谨性又能避免不必要的错误。

2.5、基本数据类型转换

自动类型转换

容量小的类型自动转换为容量大的数据类型,数据类型按容量大小排序为:

int count = 66;
double number = count;		// 自动提升运算,提升为double
System.out.println(number);

byte、short、char之间不会相互转换,他们三者在计算时首先转换为int类型

boolean类型不能与其它数据类型运算

注:当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。

强制类型转换

要把容量大的类型转换为容量小的数据类型,必须要进行强制类型转换

double count = 3.14;
int b = (int) count;	// 强制装换为int类型
System.out.println(b);

注:在把高容量装换到低容量的时候,强制转换的时候可能会存在内存溢出,或者精度丢失问题

2.6、字符串类型

String不是基本数据类型,属于引用数据类型

一个字符串可以拼接另一个字符串,也可以直接拼接其他类型的数据

String str = "hello world!";
System.out.println(str);

注:String可以和8种基本数据类型变量做运算,且运算只能是连接运算运算结果仍是String类型!

2.7、计算机的存储规则

在计算机中,任意数据最终都是以二进制的形式来存储的。包括文本(数字、字母、汉字)、图片、声音、视频等

世界上有2种人 ,认识和不认识二进制的

数字存储

进制的分类
  • 十进制(decimal)
    • 数字组成:0-9
    • 进位规则:逢十进一,借一当十,正常写,代码前面不需要加任何前缀
  • 二进制(binary)
    • 数字组成:0-1
    • 进位规则:逢二进一,代码中以0b0B开头
  • 八进制(octal):很少使用
    • 数字组成:0-7
    • 进位规则:逢八进一,代码中以数字0开头表示
  • 十六进制
    • 组成部分:0-9,a-f
    • 进位规则:逢十六进一,代码中以0x0X开头表示。此处的 a-f 不区分大小写
public static void main(String[] args) {
    int x = 100;        // 十进制
    int y = 0b1101;     // 二进制
    int z = 056;        // 八进制
    int q = 0X35a;      // 十六进制

    System.out.println(x);	// 100
    System.out.println(y);	// 13
    System.out.println(z);	// 46
    System.out.println(q);	// 858
}
进制之间相互转换
任意进制转十进制

公式:系数 * 基数的全次幂 相加

  • 系数:每一位上的数
  • 基数:当前进制数
  • 从右往左,依次为 0 1 2 3 4 5 6 ……

在这里插入图片描述

二进制转十进制

8421快速转换法

每一位二进制值的1都是代表一个固定数值

把每一位的1代表的十进制数加起来得到的结果就是它所代表的十进制数

在这里插入图片描述

十进制转其他进制

除基取余法

不断的除以基数(几进制,基数就是几)得到余数,直到商为0,再将余数倒着拼起来即可

在这里插入图片描述

字母存储:ASCII (American Standard Code for Information Interchange)码表:美国信息交换标准代码表

详见菜鸟教程

汉字存储

  • GB2312编码:1981年5月1日发布的简体中文汉字编码国家标准。收录7445个图形字符,其中包括6763个汉字
  • BIG5编码:台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施
  • GBK编码:2000年3月17日发布,收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字
  • Unicode编码(万国码):国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码, 以满足跨语言、跨平台的文本信息转换

图片存储:通过每一个像素点中RGB三原色来存储

声音存储:对声音的波形图进行采样再进行存储

2.8、运算符

运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等

  • 算术运算符 +,-,*,/,%,++,- -

    • % 取模(取余)
    • 前++ 先运算,后取值
    • 后++ 先取值,后运算
    • – 同理
  • 赋值运算符 =、+=、-=、*=、/=、%=

    • =两侧数据类型不一致时,可以使用自动类型转换或强制类型转换原则进行处理
    • 支持连续赋值
    // 连续赋值
    // 方式一
    int num1 = 10, num2 = 20;
    // 方式二
    int count1, count2;
    count1 = count2 = 20;
    
    byte number1 = 20;
    number1 = number1 + 5;  // 编译不通过
    byte number2 = 20;
    number2 += 5;   // 编译通过,+= 这种方式不会改变其本身的数据类型
    System.out.println(number2);
    
  • 比较运算符(关系运算符) >,<,>=,<=,==,!=

    • 比较运算符的结果都是boolean型,也就是说要么是true,要么是false

    • 比较运算符==不能误写成=

      // = 和 == 的区别
      boolean k1 = true;
      boolean k2 = false;
      System.out.println(k2 == k1);   // 双等比较 false
      System.out.println(k2 = k1);    // 单等赋值 true
      
  • 逻辑运算符 &&,||,!

  • 位运算符 &,|,^,>>,<<,>>>(不常用)

  • 三元运算符 (条件表达式) ? 表达式1 : 表达式2

    // 比较两个整数的较大值
    int m = 99,n  = 88; 
    int max = (m > n) ? m : n;
    System.out.println("两者比较最大值为:" + max);
    

三元运算符与if-else的联系与区别:

  1. 三元运算符可简化if-else语句
  2. 三元运算符要求必须返回一个结果
  3. if后的代码块可有多个语句

2.9、包机制

为了更好地组织类,Java提供包机制,用于区别类名的命名空间

package pkg1 pkg2 pkg3...;

一般利用公司域名倒置作为包名 www.baidu.com com.baidu.www

为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包,使用import语句可完成此功能

import pkg1 pkg2 pkg3...;
import com.zhang.base.*;		//导入这个包下所有的类

3、程序流程控制


流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块

其流程控制方式采用结构化程序设计中规定的三种基本流程结构,即:

  • 顺序结构
    • 程序从上到下逐行地执行,中间没有任何判断和跳转
  • 选择结构
    • 根据条件,选择性地执行某段代码
    • 有if…else和switch-case两种分支语句
  • 循环结构
    • 根据循环条件,重复性的执行某段代码
    • 有while、do…while、for三种循环语句

注:JDK1.5提供了foreach循环`,方便的遍历集合、数组元素

3.1、顺序结构

是按照自上而下的顺序执行的,也是任何一个算法都离不开的一种基本算法结构,也是最为简单的算法结构

3.2、选择结构

  • if单选择结构
  • if双选择结构
  • 多重if选择结构
  • 嵌套if选择结构
  • switch多选择结构
if单选择结构
if(条件表达式){
    //执行代码块
}
if双选择结构
if(条件表达式){
    //执行代码块1
}else{
    //执行代码块2
}
多重if选择结构
if(条件表达式1){
    //如果条件表达式1为true执行代码
}else if(条件表达式2){
    //如果条件表达式2为true执行代码
}else if(条件表达式3){
    //如果条件表达式3为true执行代码
}else{
    //如果以上条件表达式都不为true将执行代码
}

注:多重if选择结构常用于区间判断

嵌套if选择结构
if(条件表达式1) {
    //如果条件表达式1的值为true执行代码
    if(条件表达式2){
        //如果条件表达式2的值为true执行代码
    }else{
        //如果条件表达式2的值为false执行代码
    }
}else{
    //如果条件表达式1的值为false执行代码
}
if-else使用说明
  • 条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量
  • 语句块只有一条执行语句时,一对{}可以省略,但建议保留
switch多选择结构
  • 多选择结构还有一个实现方式就是switch case语句
  • switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
int num = 6;
switch (num){
    case 1:
        //语句
        break;  //可选
    case 2:
        //语句
        break;  //可选
    case 3:
        //语句
        break;  //可选
    case 4:
        //语句
        break;  //可选
        //可以有任意数量的case语句
    default:    //可选
        break;  //可选
}

switch语句有关规则:

  • switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举(jdk 5.0)String (jdk 7.0)
  • case子句中的值必须是常量,不能是变量名或不确定的表达式值
  • break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾
  • default子句是可选的。同时,位置也是灵活的。当没有匹配的case时,执行default

注:switch常用于等值判断

凡是可以使用switch-case的,都可以改写为if-else。反之则不成立

Java随机数

通过Math.random()来获取随机数。实际上,它返回的是0(包含)到1(不包含)之间的double值

public static void main(String[] args) {
    // 随机生成三位随机数
    for (int i = 0; i < 6; i++) {
        // 公式:(最大 - 最小 + 1) + 最小
        // 999 100 
        int number = (int) ((Math.random() * 999-100+1) + 100);
        System.out.println(number);
    }
}

3.3、循环结构

循环结构:在某些条件满足的情况下,反复执行特定代码的功能

循环语句的四个组成部分

  • 初始化部分(init_statement)
  • 循环条件部分(test_exp)
  • 循环体部分(body_statement)
  • 迭代部分(alter_statement)
循环语句分类
while 循环
while (布尔表达式){
    // 循环体
}
  • 只要布尔表达式为true,循环就会一直执行下去
  • 大多数情况是会让循环停止下来的,此时需要一个让表达式失效的方式来结束循环
  • 循环条件一直为true就会造成无限循环[死循环],正常的业务编程中应该尽量避免死循环,会影响程序性能或者造成程序卡死崩溃
do-while 循环
do {
    // 代码语句
}while (布尔表达式);
  • 对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次
  • do…while循环和while循环相似,不同的是,do…while 循环至少会执行一次

while和do…while的区别:

  • while先判断后执行,do while是先执行后判断
  • do…while总是保证循环体会被至少执行一次!这是他们的主要差别
for 循环
for (初始化;布尔表达式;更新迭代){
    // 循环体
}
  • for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构
  • for循环执行的次数是在执行前就确定的。

for循环执行顺序:参数初始化–>条件判断–>循环体–>更新迭代变量

for (;;){
    System.out.println("test");		// 死循环
}

foreach循环(SE5)

for(元素类型t  元素变量x : 数组或集合对象){
         // 引用了x的java语句
}

增强for循环是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。它的内部原理其实是个Iterator迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作

三大循环应用场景

  • 循环次数确定的情况,通常选用for循环
  • 循环次数不确定的情况,通常选用while或do-while循环
  • foreach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高
  • foreach不能对数组或集合进行修改(添加删除操作),如果想要修改就要用for循环

3.4、break&continue

  • break在任何循环语句的主体部分,均可用break控制循环的流程。break用于终止循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
  • continue语句用在循环语句体中,用于跳出本次循环,进入下一次循环

3.5、二重循环

什么是二重循环?

  • 二重循环顾名思义就是循环中嵌套另一个循环
  • 在二重循环中,外层循环变量变化一次,内层循环变量要从初始值到结束值变化一遍(外层循环一次,内层循环一遍)
  • break:跳出本层循环,continue:继续本层的下一轮循环
  • **技巧:**从二维图形的角度看,外层循环控制行数,内层循环控制列数
  • **开发经验:**实际开发中,最多见到的嵌套循环是两层。一般不会出现超过三层的嵌套循环。如果将要出现,一定要停下来重新梳理业务逻辑,重新思考算法的实现,控制在三层以内。否则,可读性会很差

图形打印:

// 打印5行直角三角形
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <=i ; j++) {
        System.out.print("*");
    }
    System.out.println();
}

// 打印5行倒直角三角形
for (int i = 1; i <= 5; i++) {
    for (int j = 5; j >= i; j--) {
        System.out.print("*");
    }
    System.out.println();
}

// 打印九九乘法表
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();
}

// 打印"菱形"
// 打印上半部分
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= 10 - 2 * i; j++) {
        System.out.print(" ");
    }
    for (int x = 1; x <= 2 * i - 1; x++) {
        System.out.print("* ");
    }
    System.out.println();
}

// 下半部分
for (int i = 1; i <= 4; i++) {
    // -
    for (int j = 1; j <= 2 * i; j++) {
        System.out.print(" ");
    }

    // *
    for (int k = 1; k <= 9 - 2 * i; k++) {
        System.out.print("* ");
    }
    System.out.println();
}

4、方法


4.1、什么是方法?

Java方法时语句的集合,它们在一起执行一个功能

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样有利于后期的扩展

命名规则:驼峰命名

4.2、方法的定义

Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

  • 修饰符:这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。

  • 返回值类型:方法可能会返回值。returnValue Type是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值,在这种情况下,returnValue Type是关键字void

  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。(见名知意

  • 参数列表:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指参数的顺序和参数的个数。参数是可选的,可有可无可多个。(参数类型,参数名

    • 形式参数:在方法被调用时用于接收外界输入的数据。
    • 实参: 调用方法时实际传给方法的数据。

    方法体:方法体包含具体的语句,定义该方法的功能。

语法格式:

// [访问修饰符] 返回值类型 方法名 (参数类型  形式参数,参数类型  形式参数...){
	...
	// 方法体
	...
	return 返回值;		// 作用: 结束方法、返回结果
}

注:

  • 方法不调用就不执行
  • 方法形参和实参传递的类型要一一对应
  • return的返回值必须要跟返回值类型相同

4.3、方法调用

  • 调用方法:对象名.方法名(实参列表)
  • Java支持两种调用方法的方式,根据方法是否有返回值来选择
  • 当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int result = compare(5, 6);

如果方法返回值是void,方法调用一定是一条语句

4.4、方法的重载

在Java中,同一个类中的多个方法可以有相同的方法名称,但是有不同的参数列表,这就称为方法重载(method overloading)

方法的重载的规则

  • 在同一个类中,方法名称必须相同
  • 参数列表必须不同(参数的类型、参数的个数、参数的顺序)
  • 与返回值、访问修饰符无关
  • 仅仅返回类型不同不足以称为方法的重载

实现理论

方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错,这叫做重载分辨

4.5、可变参数

  • JDK 1.5开始,Java支持传递同类型的可变参数给一个方法。
  • 在方法声明中,在指定参数类型后加一个省略号(…)。
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明
public void getMax(double... number){
    if (number.length == 0) {
        System.out.println("No number");
        return;
    }
    double result = number[0];      // 默认是第一个数是数组最大的值
    for (int i = 1; i < number.length; i++) {
        if (result < number[i]) {
            result = number[i];
        }
    }
    System.out.println("The Max is:" + result);
}

4.6、静态方法static(类方法)和 非静态方法(实例方法)的区别

静态变量:被static修饰的成员变量,叫做静态变量,被static修饰的成员方法,叫做静态方法

特点:被该类所有对象共享

  1. 调用对象、引用变量不同
    • 静态方法,是使用static关键字修饰的方法,又叫类方法。属于类的,不属于对象。(静态属性,静态方法都是属于类的,所以可以直接通过类名调用)。
    • 非静态方法,是不含有static关键字修饰的普通方法,又称为实例方法。属于对象的,不属于类的。(成员属性,成员方法是属于对象的,必须通过new关键字创建对象后,再通过对象调用)。
  2. 调用方法不同
    • 静态方法可以直接调用,类名调用和对象调用。(类名.方法名 / 对象名.方法名
      但是非静态方法只能通过对象调用。(对象名.方法名
  3. 生命周期不同
    • 静态方法的生命周期跟相应的类一样长,静态方法和静态变量会随着类的定义而被分配和装载入内存中(随着类的加载而加载,优先于对象存在)。一直到线程结束,静态属性和方法才会被销毁。(也就是静态方法属于类)
    • 非静态方法的生命周期和类的实例化对象一样长,只有当类实例化了一个对象,非静态方法才会被创建,而当这个对象被销毁时,非静态方法也马上被销毁。(也就是非静态方法属于对象)

总结:类方法可以直接通过类名调用,实例方法必需先实例化类,再初始化对象,然后通过类的实例对象才能调用

注:static可以用来修饰属性、方法和代码块

// 2.赋初值
{
    System.out.println("匿名代码块");
}
// 1.只执行一次
static {
    System.out.println("静态代码块");
}
// 3
public Pet() {
    System.out.println("构造方法");
}

执行顺序:静态代码块–>匿名代码块–>构造方法

注:

  • 静态方法只能访问静态变量和静态方法
  • 非静态方法可以访问所有
  • 静态方法中没有this关键字

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

局部变量成员变量
定义位置方法内。方法声明上(形参)类的内部,方法的外部
默认值无默认值,使用前需要赋初值有默认值,int 0、String null
内存位置不同栈内存堆内存
声明周期不同随着方法的调用而存在,随着方法的运行结束而消失随着对象的创建而存在,随着对象的消失而消失
作用域当前方法中有效整个类中有效

5、数组


5.1、什么是数组?

  • 数组是多个相同数据类型的有序集合
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们

5.2、数组声明创建

必须先声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:

int[] num;	// 声明数组
num = new int[5];	// 分配空间 使用new操作符来创建数组
num[0] = 99;	// 数组元素赋值
num[1] = 88;
num[2] = 77;
......

System.out.println(num[0]);		// 使用,访问数组中第一个元素

// 声明数组并分配空间
int[] arr = new int[5];
arr[0] = 66;	// 数组元素赋值
arr[1] = 77;
.....
    
// 声明数组分配空间并赋值
int[] arr2 = {55,66,77}; 
// 等同于==>  int[] arr2 = new int[]{55,66,77};	// 不能指定数组长度
  • 数组的元素是通过索引访问的,数组索引从0开始
  • 获取数组长度:arrays.length

数组的基本特点:

  • 其长度是确定的,数组一旦被创建,它的大小就是不可以改变的
  • 其元素必须是相同类型,不允许出现混合类型
  • 数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型

数组边界

下标的合法区间:[0,length-1]

数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutOfBoundsException:数组下标越界异常

5.3、三种初始化

静态初始化

除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值

String[] goods = {"鱼香肉丝", "宫保鸡丁", "手撕包菜","大盘鸡","烧茄子"};

动态初始化

数组定义与为数组元素分配空间并赋值的操作分开进行

int[] arr = new int[5];
arr[0] = 10;
arr[1] = 36;
arr[2] = 95;
arr[3] = 82;

默认初始化

  • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
int[] arr = new int[5];
double[] db = new double[5];
boolean[] bool = new boolean[5];
char[] chars = new char[5];
String[] str = new String[5];

System.out.println(arr[0]);     // 默认值 0
System.out.println(db[0]);      // 默认值 0.0
System.out.println(bool[0]);    // 默认值 false
System.out.println(chars[0]);    // 0
System.out.println(str[0]);     // 默认值 null

5.4、数组遍历

  • 普通for循环
int[] arrays = {66, 11, 22, 55, 84, 85};
// 打印数组中的全部元素
for (int i = 0; i < arrays.length; i++) {
    System.out.print(arrays[i] + "\t");
}
  • for-each循环
// 没有下标 常用于遍历值
for (int num : arrays) {
    System.out.print(num + "\t");
}
  • 数组作方法参数
public static void printArrays(int[] arr) {
    System.out.println("数组元素为:");
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }
}

printArrays(arrays);	// 调用显示数组元素方法

5.5、二维数组

什么是二维数组?

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其中每一个元素都是一个一维数组

二维数组的定义及使用

int[][] arrays = {{11, 22, 33}, {99, 88, 77}, {100, 200, 300}};
System.out.println(arrays[0][2]);       // 33
System.out.println(arrays[1][0]);       // 99
System.out.println(arrays[2][1]);       // 200

/**
* 遍历二维数组
*/
for (int i = 0; i < arrays.length; i++) {
    for (int j = 0; j < arrays[i].length; j++) {
        System.out.print(arrays[i][j] + "\t");
    }
}

小案例

// 使用二维数组,存储每个季度的营业额,并计算每个季度的营业额和全年营业额(单位:万)
double[][] turnover = {{12.5, 16.2, 18.5, 20}, {8.5, 9.6, 8.0, 10.6}, {16, 22.6, 17.2, 16.6}};

// 计算全年总营业额
double fillYearTurnover = 0.0;

for (int i = 0; i < turnover.length; i++) {
    // 计算每个季度营业额
    double seasonTurnover = 0.0;
    for (int j = 0; j < turnover[i].length; j++) {
        fillYearTurnover += turnover[i][j];
        seasonTurnover += turnover[i][j];
    }
    System.out.println("第" + (i + 1) + "季度营业额为:" + seasonTurnover + "万元");
}
System.out.println("全年总营业额为:" + fillYearTurnover + "万元");
数组常见算法

数组元素反转

int[] arr = {95, 84, 32, 48, 36, 18, 35, 68, 89, 100};
System.out.println("交换之前:");
for (int i : arr) {
    System.out.print(i + "\t");
}

// 方式一:
for (int i = 0; i < arr.length / 2; i++) {
    // 交换 arr[i] 和 arr[arr.length - 1 - i]位置的元素
    int temp = arr[i];
    arr[i] = arr[arr.length - 1 - i];
    arr[arr.length - 1 - i] = temp;
}

// 方式二:
// for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
    // int temp = arr[i];
    // arr[i] = arr[j];
    // arr[j] = temp;
// }

System.out.println("\n交换之后:");
for (int i : arr) {
    System.out.print(i + "\t");
}

查找指定元素在数组中的索引位置(线性查找)

int[] arr = {64, 949, 94, 36, 494, 87, 65, 99};
int findEle = 36;

boolean flag = true;
for (int i = 0; i < arr.length; i++) {
    if (findEle == arr[i]) {
        flag = false;
        System.out.println("找到了" + findEle + ",索引为:" + i);
        break;
    }
}

if (flag){
    System.out.println("没有找到你需要的数值");
}

查找指定元素在数组中的索引位置(二分查找)

// 二分法查找:要求数组必须是有序的
int[] arr = new int[]{0, 2, 8, 33, 43, 256, 566,867};
int target = 256;

int head = 0;           // 默认首索引
int end = arr.length - 1;      // 默认尾索引
boolean flag = false;       // 判断是否找到了指定元素
while (head <= end) {
    int middle = (head + end) / 2;
    if (target == arr[middle]) {
        System.out.println("找到了" + target + "对应索引为:" + middle);
        flag = true;
        break;
    } else if (target > arr[middle]) {
        head = middle + 1;
    } else {
        head = middle - 1;
    }
}

if (!flag) {
    System.out.println("未找到你想要的元素");
}

冒泡排序

public static void main(String[] args) {
    int[] arr = {46, 2, 816, 494, 16, 84, 31, 99, 91, 15};
    int[] sortArr = bubbleSort(arr);
    for (int i : sortArr) {
        System.out.print(i + "\t");
    }
}

public static int[] bubbleSort(int[] sortArr) {
    for (int i = 0; i < sortArr.length - 1; i++) {
        boolean flag = true;        // 默认已经排好序

        // 内层循环,比较判断两个数,如果第一个数比第二个数大,则交换位置
        for (int j = 0; j < sortArr.length - 1 - i; j++) {
            if (sortArr[j] > sortArr[j + 1]) {
                int temp = sortArr[j];
                sortArr[j] = sortArr[j + 1];
                sortArr[j + 1] = temp;
                flag = false;       // 如果元素发生了交换,那么说明数组还没有排好序
            }
        }
        if (flag) {
            break;      // 如果flag依然为true,说明已经排好序,可以提前终止循环,从而减少比较次数和交换次数,提高排序效率
        }
    }
    return sortArr;
}

5.6、Arrays工具类

Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用

int[] arr1 = {99, 88, 77, 66, 55};
int[] arr2 = {99, 88, 77, 66, 55};
boolean flag = Arrays.equals(arr1, arr2);       // 比较两个数组中的值是否相等
System.out.println("flag = " + flag);		// true

System.out.println(Arrays.toString(arr1));      // 输出数组元素信息

Arrays.sort(arr1);      // 使用排序算法快速排序(升序)
System.out.println(Arrays.toString(arr1));

Arrays.fill(arr2, 66);       // 将指定值填充到数组中
System.out.println(Arrays.toString(arr2));		// arr2数组中值全部为66

// (二分查找) 前提条件:传递的数组必须是有序的
int index = Arrays.binarySearch(arr1, 88);
System.out.println("index = " + index);	 // 3

int[] originArr = {100, 200, 300, 600, 700};
// 将指定数组的指定范围复制到新数组中
int[] copyRangeArr = Arrays.copyOfRange(originArr, 3, originArr.length);
System.out.println(Arrays.toString(copyRangeArr));      // [600,700]

5.7、内存分析

Java内存分析

  • 存放对象和数组,new出来的,都存储在堆内存
  • 可以被所有的线程共享,不会存放别的对象引用

  • 存放基本变量类型(包含这个基本类型的具体数值)
  • 引用对象的变量(会存放引用在堆里面的具体地址值)

方法区

  • 可以被所有的线程共享
  • 包含了所有的class和static变量

5.8、基本数据类型与引用数据类型

  • 基本数据类型:数据值是存储在自己的空间中
  • 特点:赋值给其他变量,也是赋的真实的值
  • 引用数据类型:数据值是存储在其他空间中(堆),自己空间中存储的是地址值
  • 特点:赋值给其他变量,赋的地址值
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值