语言:人与人交流沟通的表达方式
计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言
Java是一门非常火的计算机语言。(也叫做编程语言)
我们想要让计算机做一些事情,那么就可以通过Java语言告诉计算机就可以了
是其他两个版本的基础。
Java语言的小型版,用于嵌入式消费类电子设备或者小型移动设备的开发。
其中最为主要的还是小型移动设备的开发(手机)。渐渐的没落了,已经被安卓和苹果给替代了
用于Web方向的网站开发。(主要从事后台服务器的开发)
在服务器领域,Java是当之无愧的老大。
Java语言跨平台的原理:
操作系统本身是不认识Java语言的,针对于不同的操作系统,Java提供了不同的虚拟机,虚拟机会把Java语言翻译成操作系统能看得懂的语言。
JVM(Java Virtual Machine)Java虚拟机
JRE(Java Runtime Environment)Java运行环境,包含了JVM和Java的核心类库(Java API)
JDK(Java Development Kit)Java开发工具,包含了JRE和开发工具
这里只做简单介绍,小白请看
jdk 安装与配置环境(windows系统)
官方链接:
http://www.oracle.com
注意:
不同的操作系统,需要下载对应版本的JDK
电脑是windows32位的,就装32位的,64位的就装64位的JDK
Java从9版本开始,不提供32位版本的安装包了
默认的安装路径是在C:\Program Files下。
注意:(若自定义安装路径)
安装路径不要有中文,不要有空格等一些特殊符号
开发Java程序,需要使用JDK提供的开发工具(比如javac.exe、java.exe等命令),而这些工具在JDK的安装目录的bin目录下,如果不配置环境变量,那么这些命令只可以在bin目录下使用,而我们想要在任意目录下都能使用,所以就要配置环境变量,把这个软件的路径配置到环境变量中的PATH里面。
注意:下载老版本的JDK是没有自动配置的,而且自动配置的只包含了4个工具
步骤:
方式:
①JAVA_HOME:告诉操作系统JDK安装在了哪个位置(未来其他技术要通过这个找JDK)
②Path:告诉操作系统JDK提供的javac(编译)、java(执行)命令安装到了哪个位置
目录名称 | 说明 |
---|---|
bin | 该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。 |
conf | 该路径下存放了JDK的相关配置文件。 |
include | 该路径下存放了一些平台特定的头文件。 |
jmods | 该路径下存放了JDK的各种模块。 |
legal | 该路径下存放了JDK各模块的授权文档。 |
lib | 该路径下存放了JDK工具的一些补充JAR包。 |
在windows操作系统中,利用利用cmd命令去操作计算机,比如:打开文件,打开文件夹,创建文件夹等。
按下快捷键:win + R
在运行窗口中输出 cmd
输出回车
操作 | 说明 |
---|---|
E: 盘符名称*** | 表示切换到E盘,盘符切换 |
dir | 查看当前路径下的内容 |
cd 目录 | 进入单级目录 |
cd … | 回退到上一级目录 |
cd 目录1\目录2… | 进入多级目录 |
cd \ | 回退到盘符目录 |
cls | 清屏 |
exit | 退出命令提示符窗口 |
注意:
在windows操作系统中,文件名或者文件夹名是忽略大小写的。
注意:后缀名为java的才是java文件。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
注意:未保存的文件在左上角会有*符号标记
编译文件。编译后会产生一个class文件。
java文件:程序员自己编写的代码。
class文件:交给计算机执行的文件。
运行代码
注意:运行的是编译之后的class文件。
用到两个命令:
javac + 文件名 + 后缀名 (就是编译java文件)
java + 文件名(运行编译之后的class文件)
运行结果:
IDEA概述:
IDEA全称IntelliJ IDEA,是用于Java语言开发的集成环境,它是目前公认的Java程序开发最好的工具。
集成环境:
把代码编写,编译,执行,调试等多种功能综合到一起的开发工具。
下载官网:
https://www.jetbrains.com/idea
安装详细步骤请查看:
IDEA 下载与安装
单行注释:
// 单行注释
多行注释:
/*
多行注释
...
*/
注意:多行注释不能嵌套使用。
文档注释:
/**
也是多行注释
...
*/
被Java赋予了特定含义的英文单词,所有关键字都是小写字母
abstract | assert | boolean | break | byte |
---|---|---|---|---|
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
作用:告诉程序员,数据在程序中的书写格式。
字面量类型 | 说明 | 写法 |
---|---|---|
整数 | 不带小数的数字 | 666,-88 |
小数 | 带小数的数字 | 13.14,-5.21 |
字符 | 必须使用单引号,有且仅能一个字符 | ‘A’,‘0’, ‘我’ |
字符串 | 必须使用双引号,内容可有可无 | “HelloWorld” |
布尔值 | 布尔值,表示真假 | true 、false |
空值 | 一个特殊的值,空值 | 值是:null |
public class literal {
public static void main(String[] args) {
System.out.println(10); // 输出一个整数
System.out.println(5.5); // 输出一个小数
System.out.println('a'); // 输出一个字符
System.out.println(true); // 输出boolean值true
System.out.println("HelloWorld"); // 输出字符串
System.out.println("null"); // 输出null
}
}
运行结果:
可以看作存储数据的容器,但只能存一个值
定义:
数据类型 变量名 = 数据值;
int x=1;
数据类型:规定变量当中能存储什么类型的数据
变量名:容器的命名
数据值:存储在容器中的数据
分 号:Java语法规定以分号结束
注意:
必须遵循,否则代码会报错
见名知意,如果不这样做,代码虽然不会报错,但是同事看你的代码会很难受
小驼峰命名法:适用于变量名和方法名
如果是一个单词,那么全部小写,比如:name
如果是多个单词,那么从第二个单词开始,首字母大写,比如:firstName、maxAge
大驼峰命名法:适用于类名
如果是一个单词,那么首字母大写。比如:Demo、Test。
如果是多个单词,那么每一个单词首字母都需要大写。比如:HelloWorld
注意:
数据类型 | 关键字 | 内存占用 | 取值范围 |
---|---|---|---|
整数 | byte | 1 | -128~127 |
short | 2 | -32768~32767 | |
int | 4 | 负的2的31次方 ~ 2的31次方-1 | |
long | 8 | 负的2的63次方 ~ 2的63次方-1 | |
浮点数 | float | 4 | 1.401298e-45 ~ 3.402823e+38 |
double | 8 | 4.9000000e-324 ~ 1.797693e+308 | |
字符 | char | 2 | 0-65535 |
布尔 | boolean | 1 | true,false |
补充:
double > float > long > int > short > byte
注意:
就是把一个取值范围小的数据或变量,自动赋值给另一个取值范围大的变量
转换规则:
取值范围大小关系:
double > float > long > int > short > byte
我们要把一个取值范围大的数据或变量赋值给另一个取值范围小的变量,是不允许的
如果一定要这么干,就需要加入强制转换
格式:
//目标数据类型 变量名 = (目标数据类型)被强转的数据;
public class Mandatory {
public static void main(String[] args) {
double x = 1.3;
int y = (int) x;
System.out.println(y); //1
}
}
注意:
强制转换有可能会导致数据发生错误(数据精度丢失)
字符串的+操作
1 + "abc" + 1 //1abc1
1 + 2 + "abc" + 2 + 1 //3abc21
字符的+操作
当+操作中出现字符时,此时会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后进行计算
char a = 'a'; //ASCII码表中a=97
int result = a + 0;
System.out.println(result); //97
Java已经帮我们写好了,不需要我们自己写了,我们只需导入Scanner这个类就可以直接使用了
如:
//导包,导入Scanner类
import java.util.Scanner;
public class ScannerUse{
public static void main(String[] args){
//创建对象,使用Scanner这个类
Scanner sc = new Scanner(System.in);
//接收数据,用变量x接收传入的数据
System.out.println("请输入一个数字:");
int x = sc.nextInt();
System.out.println("输入的x值为:" + x);
}
}
运行结果:
方法 | 说明 |
---|---|
next() | 可以接受任意数据,返回的是一个字符串 |
nextLine() | 可以接受任意数据,返回的是一个字符串 |
nextInt() | 只接受整数,录入小数或者其他字母,就会报错 |
nextDouble() | 能接收整数和小数,但是都会以小数返回,录入字母会报错 |
注意:
next(),nextInt(),nextDouble()在接收数据的时候,会遇到空格,回车,制表符其中一个就会停止接收数据。
next(),nextInt(),nextDouble()在接收数据的时候,会遇到空格,回车,制表符其中一个就会停止接收数据。但是这些符号 + 后面的数据还在内存中并没有接收。如果后面还有其他键盘录入的方法,会自动将这些数据接收。
nextLine()方法遇到回车停止接收数据,是把一整行全部接收完毕
对常量或者变量进行操作的符号
算术运算符 | 运算说明 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取模、取余,除法运算,获取的是余数 |
表达式:
System.out.println( 1 + 1); //3
System.out.println( 1 * 3); //3
System.out.println( 10 / 3); //3
System.out.println(10.0 / 3); //3.3333333333333335
注意:
自增自减运算符 | 运算说明 |
---|---|
++ | 把变量里面的值+1 |
– | 把变量里面的值-1 |
表达式:
int a = 10;
a++;
System.out.println(a); //11
++a;
System.out.println(a); //12
注意:
不管是先++,还是后++,单独写在一行的时候,运算结果是一模一样的
赋值运算符 | 运算说明 |
---|---|
= | 等号右边的结果,赋值给左边的变量 |
+= | 符号左边跟右边进行运算,将最终的结果赋值给左边 |
-= | 符号左边跟右边进行运算,将最终的结果赋值给左边 |
*= | 符号左边跟右边进行运算,将最终的结果赋值给左边 |
/= | 符号左边跟右边进行运算,将最终的结果赋值给左边 |
%= | 符号左边跟右边进行运算,将最终的结果赋值给左边 |
如:
public class Expand {
public static void main(String[] args) {
byte a = 10;
byte b = 10;
a += b; //这里做了一个强制转换为byte
//a = (byte)(a + b);
System.out.println(a);//20
}
}
注意:
扩展的赋值运算符中隐层还包含了一个强制转换。
又叫比较运算符,其实就是拿着左边跟右边进行了判断而已。
关系运算符 | 运算说明 |
---|---|
== | 判断左边跟右边是否相等,如果成立就是true,如果不成立就是false |
!= | 判断左边跟右边是否不相等,如果成立就是true,如果不成立就是false |
> | 判断左边是否大于右边,如果成立就是true,如果不成立就是false |
>= | 判断左边是否大于等于右边,如果成立就是true,如果不成立就是false |
< | 判断左边是否小于右边,如果成立就是true,如果不成立就是false |
<= | 就是判断左边是否小于等于右边,如果成立就是true,如果不成立就是false |
注意:
关系运算符最终的结果一定是布尔类型的。要么是true,要么是false
逻辑运算符 | 运算说明 |
---|---|
& | 与;两边都为真,结果才为真,只要有一个为假,那么结果就是假 |
| | 或;两边都为假,结果才为假,只要有一个为真,那么结果就是真 |
^ | 异或;两边都相同,结果为false,如果两边不同,结果为true |
! | 取反;false取反就是true,true取反就是false |
&& | 与;两边都为真,结果才为真,只要有一个为假,那么结果就是假(具有短路效果) |
|| | 或;两边都为假,结果才为假,只要有一个为真,那么结果就是真具有(短路效果) |
短路效果:
当左边不能确定整个表达式的结果,右边才会执行。当左边能确定整个表达式的结果,那么右边就不会执行了。优点是提高了代码的运行效率。
注意:
&& 和 & 、||和|的运行结果都是一模一样的,只不过具有短路效果
又叫做:三元表达式或者问号冒号表达式。
三元运算符 | 运算说明 |
---|---|
?: | 计算关系表达式的值 |
表达式:
//关系表达式 ? 表达式1 :表达式2;
/*
如果关系表达式的值为真,那么执行表达式1,为假则执行表达式2
*/
public class Ternary {
public static void main(String[] args) {
int a = 10;
int b = 20;
int max = a>b ? a:b;
System.out.println(max);//20
}
}
运行结果:
注意:
三元运算符的最终结果一定要被使用,要么赋值给一个变量,要么直接输出。
优先级 | 运算符 | 结合性 |
---|---|---|
1 | ( ) [ ] . | 从左到右 |
2 | ! ~ ++ – | 从右到左 |
3 | * / % | 从左到右 |
4 | + - | 从左到右 |
5 | << >> >>> | 从左到右 |
6 | < <= > >= instanceof | 从左到右 |
7 | == != | 从左到右 |
8 | & | 从左到右 |
9 | ^ | 从左到右 |
10 | 从左到右 | |
11 | && | 从左到右 |
12 | || | 从左到右 |
13 | ? : | 从左到右 |
14 | = += -= *= /= &= |= ^= ~= «= »= >>>= | 从左到右 |
15 | , | 从左到右 |
总结:
括号级别最高,逗号级别最低,单目 > 算术 > 位移 > 关系 > 逻辑 > 三目 > 赋值
在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。所以,我们必须清楚每条语句的执行流程。而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能,如:最常见顺序结构就是程序中最简单最基本的流程控制,按照代码的先后顺序执行
执行流程:
if (关系表达式) {
语句体;
}
执行流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QgBp70to-1665368466777)(ing/1545616039363.png)]
如:
import java.util.Scanner;
public class Beauty {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入谈过几个对象:");
int sum = sc.nextInt();
if(sum > 2) {
System.out.println("你真行!!!");
}
}
}
运行结果:
注意:
如果关系表达式是一个布尔类型的变量,可以直接把变量写在小括号中
如果大括号中的语句体只有一条,那么大括号可以省略不写
if (关系表达式) {
语句体1;
} else {
语句体2;
}
执行流程:
如:
import java.util.Scanner;
public class Beauty {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入谈过几个对象:");
int sum = sc.nextInt();
if(sum > 2) {
System.out.println("你真行!!!");
} else {
System.out.println("你真捞!!!");
}
}
}
运行结果:
if (关系表达式1) {
语句体1;
} else if (关系表达式2) {
语句体2;
}
...
else {
语句体n+1;
}
执行流程:
如:
import java.util.Scanner;
public class Beauty {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入谈过几个对象:");
int sum = sc.nextInt();
if(sum > 2) {
System.out.println("你真行!!!");
} else if(sum==2){
System.out.println("你还行!!!");
} else if(sum==1){
System.out.println("你不行!!!");
} else {
System.out.println("你真捞!!!");
}
}
}
运行结果:
不能单独存在的。可以用在switch和循环中,表示结束,终止循环
不能单独存在的。只能存在于循环当中,表示跳过本次循环,继续执行下去
switch (表达式) {
case 1:
语句体1;
break;
case 2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
执行流程:
如:
import java.util.Scanner;
public class Date {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("表示星期几(请输入一个整数)?");
int week = sc.nextInt();
switch (week){
case 1:
System.out.println("跑步");
break;
case 2:
System.out.println("出去耍");
break;
case 3:
System.out.println("钓鱼");
break;
case 4:
System.out.println("钓鱼");
break;
case 5:
System.out.println("钓鱼");
break;
case 6:
System.out.println("写代码");
break;
case 7:
System.out.println("写代码");
break;
default:
System.out.println("输入错误,没有这个星期");
break;
}
}
}
运行结果:
注意:
如:
//键盘录入星期数,输出工作日(1~5)、休息日(6~7)
Scanner sc = new Scanner(System.in);
System.out.println("请输入星期:");
int week = sc.nextInt();
//利用case穿透简化代码
switch (week){
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("工作日");
break;
case 6:
case 7:
System.out.println("休息日");
break;
default:
System.out.println("没有这个星期");
break;
}
//利用JDK12简化代码书写
switch (week) {
case 1, 2, 3, 4, 5 -> System.out.println("工作日");
case 6, 7 -> System.out.println("休息日");
default -> System.out.println("没有这个星期");
}
try {
//可能出现异常的代码
}catch(异常类型1 变量名1) {
//处理异常的方式1
}catch(异常类型2 变量名2) {
//处理异常的方式2
}
....
finally {
//一定会执行的代码
}
异常类型:
如:
public class Demo01 {
public static void main(String[] args) {
try {
int a = 10;
int b = 0;
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();
System.out.println("程序运行错误");
}finally {
System.out.println("程序运行结束!!!");
}
}
}
运行结果:
循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复 执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去形成死循环
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
初始化语句: 表示循环开启时的起始状态
条件判断语句:表示循环反复执行的条件,就是判断循环是否能一直执行下去
条件控制语句:表示循环执行中每次变化的内容,就是控制循环是否能执行下去
循环体语句: 表示循环反复执行的内容
如:
//求1-100之间的偶数和
public class Sums {
public static void main(String[] args) {
int sum = 0;
for(int i=1; i<=100; i++) {
if(i%2 == 0) {
sum += i;
}
}
System.out.println("1-100之间的偶数和是:" + sum);
}
}
运行结果:
初始化语句;
while(条件判断语句){
循环体;
条件控制语句;
}
初始化语句: 表示循环开启时的起始状态
条件判断语句:表示循环反复执行的条件,就是判断循环是否能一直执行下去
条件控制语句:表示循环执行中每次变化的内容,就是控制循环是否能执行下去
循环体语句: 表示循环反复执行的内容
如:
//求1-100之间的偶数和
public class Sums {
public static void main(String[] args) {
int sum = 0;
int i = 0;
while(i<=100) {
i++;
if(i%2 == 0) {
sum += i;
}
}
System.out.println("1-100之间的偶数和是:" + sum);
}
}
运行结果:
几乎不用
初始化语句;
do{
循环体;
条件控制语句;
}while(条件判断语句);
如:
//求1-100之间的偶数和
public class Sums {
public static void main(String[] args) {
int sum = 0;
int i = 0;
do{
if(i%2 == 0) {
sum += i;
i++
}while(i<=100);
}
System.out.println("1-100之间的偶数和是:" + sum);
}
}
运行结果:
特点:
先执行,再判断
概念:
指的是一种容器,可以用来存储同种数据类型的多个值,但是在存储数据的时候,需要考虑隐式转换
比如:定义了一个int类型的数组,那么boolean、double类型的数据是不能存到这个数组中的,但是byte类型,short类型,int类型的数据又可以存到这个数组里面的
格式:
数据类型 [] 数组名
或:
数据类型 数组名 []
int [] sum
int sum []
两种格式所表达的效果都是一样的
数据类型:限定了数组能存什么类型的数据
方括号:表示现在定义的是一个数组
数组名:数组的名字
格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...};
简化:
数据类型[] 数组名 = {元素1,元素2,元素3,元素4...};
int[] sum = new int[]{11,22,33};
double[] sum ={1.1,1.2,1.3};
数据类型:限定了数组能存什么类型的数据,前、后的数据类型一定要保持一致
方括号:表示现在定义的是一个数组
数组名:数组的名字
new:就是给数组在内存中开辟了一个空间
格式:
数据类型[] 数组名 = new 数据类型[数组的长度];
int[] len = new int[3];
动态数组的默认初始化值:
整数类型:0
小数类型:0.0
布尔类型:false
字符类型:‘\u0000’(空格)
引用类型:null
两种数组的区别:
静态初始化:int[] sum = new int{1,2,3,4,5};
动态初始化:int[] sum= new int[3];
静态初始化:手动指定数组的元素,系统会根据元素的个数,计算出数组的长度
动态初始化:手动指定数组长度,由系统给出默认初始化值
使用取舍:
格式:
数组名[索引];
int[] sum = {1,2,3,4,5};
//打印数组的地址
System.out.println(sum);//[I@6d03e736
//获取sum数组中,3索引上的值
int x = sum[3];
System.out.println(x);//4
//将sum数组中,3索引上的值修改为10
sum[3] = 10;
System.out.println("修改之后为:" + sum[3]);//10
索引:也叫角标、下标,就是数组容器中每一个小格子对应的编号
索引的特点:
遍历:就是把数组里面所有的内容一个一个全部取出来
数组的长度:数组名.length;
for(int i = 0; i < sum.length; i++){
//在循环的过程中,i依次表示数组中的每一个索引
System.out.println(sum[i]);
}
定义一个数组,存入1~5,打乱数组中所有元素的顺序
import java.util.Random;
public class Sums {
public static void main(String[] args) {
//1.定义数组存储1~5
int[] sum = new int[]{1, 2, 3, 4, 5};
//2.循环遍历数组,从0索引开始打乱数据的顺序
Random r = new Random();
for (int i = 0; i < sum.length; i++) {
//生成一个随机索引
int randomIndex = r.nextInt(sum.length);
//拿着随机索引指向的元素跟i指向的元素进行交换
int temp = sum[i];
sum[i] = sum[randomIndex];
sum[randomIndex] = temp;
}
//当循环结束之后,数组中所有的元素的乱顺序就打乱了
for (int i = 0; i < sum.length; i++) {
System.out.print(sum[i] + " ");
}
}
}
运行结果:
概念:
方法(method)是程序中最小的执行单元,
方法必须先创建才可以使用,该过称为方法定义,
方法创建后并不是直接可以运行的,需要手动调用后,才执行
格式:
//定义
public static void 方法名 () {
// 方法体;
}
//调用
方法名();
例:
定义一个方法,用于打印两个数字中的较大数
public class MethodTest {
public static void main(String[] args) {
//在main()方法中调用定义好的方法
getMax();
}
//定义一个方法,用于打印两个数字中的较大数,例如getMax()
public static void getMax() {
//方法中定义两个变量,用于保存两个数字
int a = 1;
int b = 10;
//使用分支语句分两种情况对两个数字的大小关系进行处理
if(a > b) {
System.out.print("max="+a);
} else {
System.out.print("max="+b);
}
}
}
注意:方法必须先定义,后调用,否则程序将报错
格式:
//定义
public static void 方法名 (参数1) {
方法体;
}
public static void 方法名 (参数1, 参数2, 参数3...) {
方法体;
}
//调用
方法名(参数);
方法名(参数1,参数2);
参数:由数据类型和变量名组成 (数据类型 变量名)
形参和实参
例:
public class MethodTest {
public static void main(String[] args) {
//在main()方法中调用定义好的方法(使用常量)
getMax(10,20);
//调用方法的时候,人家要几个,你就给几个,人家要什么类型的,你就给什么类型的,否则报错
//在main()方法中调用定义好的方法(使用变量)
int a = 1;
int b = 10;
getMax(a, b);
}
//定义一个方法,用于打印两个数字中的较大数,例如getMax()
//为方法定义两个参数,用于接收两个数字
public static void getMax(int a, int b) {
//使用分支语句分两种情况对两个数字的大小关系进行处理
if(a > b) {
System.out.print("max="+a);
} else {
System.out.print("max="+b);
}
}
}
注意:
方法定义时,参数中的数据类型与变量名都不能缺少,缺少任意一个程序将报错
方法调用时,参数的数量与类型必须与方法定义中的设置相匹配,否则程序将报错
格式
//定义
public static 数据类型 方法名 (参数) {
return 数据 ;
}
//调用
方法名 (参数);
数据类型 变量名 = 方法名 (参数) ;
例:
public class MethodTest {
public static void main(String[] args) {
//在main()方法中调用定义好的方法并使用变量保存
int result = getMax(1,10);
System.out.println("max="+result);
System.out.println("max="+getMax(10,20));
}
//定义一个方法,用于获取两个数字中的较大数
public static int getMax(int a, int b) {
//使用分支语句分两种情况对两个数字的大小关系进行处理
//根据题设分别设置两种情况下对应的返回结果
if(a > b) {
return a;
} else {
return b;
}
}
}
注意:
方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错
方法的返回值通常会使用变量接收,否则该返回值将无意义
格式:
//定义
public static 返回值类型 方法名(参数) {
方法体;
return 数据 ;
}
//调用
方法名 (参数);
public static :修饰符
返回值类型:方法操作完,返回数据的数据类型;如果方法操作完,没有返回值,写void
方法名:调用方法时候使用的标识
参数:由数据类型和变量名组成,多个参数之间用逗号隔开
方法体:完成功能的代码块
return:如果方法操作完毕,有数据返回,用于把数据返回给调用者
概念:
方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载
例:
public class MethodTest {
public static void main(String[] args) {
//调用方法
System.out.println(compare(10, 20));
System.out.println(compare((byte) 10, (byte) 20));
System.out.println(compare((short) 10, (short) 20));
System.out.println(compare(10L, 20L));
}
//int
public static boolean compare(int a, int b) {
System.out.println("int");
return a == b;
}
//byte
public static boolean compare(byte a, byte b) {
System.out.println("byte");
return a == b;
}
//short
public static boolean compare(short a, short b) {
System.out.println("short");
return a == b;
}
//long
public static boolean compare(long a, long b) {
System.out.println("long");
return a == b;
}
}
注意:
方法不能嵌套定义
如:
public class MethodTest {
public static void main(String[] args) {
}
public static void methodOne() {
public static void methodTwo() {
// 这里会引发编译错误!!!
}
}
}
void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据
如:
public class Methodtest {
public static void main(String[] args) {
}
public static void methodOne() {
//return 10; 编译错误,因为没有具体返回值类型
return;
//System.out.println(10); return语句后面不能跟数据或代码
}
}
概念:
客观存在的事物皆为对象 ,说万物皆对象
类是对事物的一种描述,对象则为具体存在的事物
类的组成是由属性和行为两部分组成
/*
public class 类名 {
// 成员变量
变量1的数据类型 变量1;
变量2的数据类型 变量2;
…
// 成员方法
方法1;
方法2;
}
*/
public class Phone {
//成员变量
String brand;
int price;
//成员方法
public void call() {
System.out.println("打电话");
}
public void sendMessage() {
System.out.println("发短信");
}
}
/*
创建对象
格式:类名 对象名 = new 类名();
范例:Phone p = new Phone();
使用对象
1:使用成员变量
格式:对象名.变量名
范例:p.brand
2:使用成员方法
格式:对象名.方法名();
范例:p.call()
*/
public class PhoneDemo {
public static void main(String[] args) {
//创建对象
Phone p = new Phone();
//使用成员变量
System.out.println(p.brand);
System.out.println(p.price);
p.brand = "小米";
p.price = 2999;
System.out.println(p.brand);
System.out.println(p.price);
//使用成员方法
p.call();
p.sendMessage();
}
}
包在操作系统中其实就是一个文件夹。用来管理不同的Java类,方便以后管理和维护。
在IDEA项目中,建包的操作如下:
包的命名:
路径名.路径名.xxx.xxx
// 例如:com.itheima.oa
导包:
什么时候需要导包?
什么时候不需要导包?
成员变量 | 局部变量 | |
---|---|---|
类中位置不同 | 类中方法外 | 方法内部或方法声明上 |
内存中位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 随着方法的调用而存在,醉着方法的调用完毕而消失 |
初始化值不同 | 有默认初始化值 | 没有默认初始化值,必须先定义,赋值才能使用 |
Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限
修饰符 | 访问权限 |
---|---|
public | 公共的,所有地方都可以访问 |
protected | 本类 ,本包,其他包中的子类都可以访问 |
默认(没有修饰符) | 本类 ,本包可以访问 |
private | 私有的,当前类可以访问 |
不同权限的访问能力:
public | protected | 默认 | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中的类 | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
public具有最大权限。private则是最小权限。
概念:
封装是面向对象三大特征之一(封装,继承,多态)
对象代表什么,就得封装对应的数据,并提供数据对应的行为
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
private是一个修饰符,可以用来修饰成员(成员变量,成员方法)
被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
例:
//定义一个学生类
class Student {
//成员变量
String name;
private int age;
//提供get/set方法
//set方法:给成员变量赋值
//get方法:对外提供成员变量
public void setAge(int a) {
if(a<0 || a>100) {
System.out.println("你给的年龄有误");
} else {
age = a;
}
}
public int getAge() {
return age;
}
//成员方法
public void show() {
System.out.println(name + "," + age);
}
}
//学生测试类
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
//给成员变量赋值
s.name = "李逍遥";
s.setAge(30);
//调用show方法
s.show();
}
}
this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题)
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void show() {
System.out.println(name + "," + age);
}
}
static关键字用来修饰成员变量和成员方法,被static修饰的成员是属于类的,是放在静态区中;没有static修饰的成员变量和方法,则是属于对象的。
所有的对象都可以共享这个变量
有static修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量。 直接可以用 类名访问。因为类只有一个,所以静态成员变量在内存区域中也只存在一份。
定义:
//修饰符 static 数据类型 变量名 = 初始值;
例:
public class Student {
//静态变量
public static String name = "圣美同学"; // 属于类,只有一份
//实例变量,不能直接调用
private int age=10; //实例成员变量属于每个对象,必须创建类的对象才可以访问
//访问
public static void main(String[] args){
System.out.println(Student.name); // 圣美同学
Student.name = "小美同学";
System.out.println(Student.name); // 小美同学
}
}
所有的对象都可以共享这个方法
有static修饰成员方法,说明这个成员方法是属于类的,这个成员方法称为类方法或者静态方法。 可以直接用 类名访问。因为类只有一个,所以静态方法在内存区域中也只存在一份。
例:
public class Student {
//静态变量
public static String name = "圣美同学"; // 属于类,只有一份。
//静态方法
public static void style() {
System.out.println("圣美在看美女");
}
//访问
public static void main(String[] args){
Student.style();
}
}
实例变量、方法:
无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。
public class Student {
// 实例变量
private String name;
// 无 static修饰,实例方法。属于每个对象,必须创建对象调用
public void age(){
System.out.println(name +"18岁");
}
//访问
public static void main(String[] args){
// 创建对象,必须创建类的对象才可以访问。
Student stu = new Student();
stu.name = "圣美";
stu.age();
}
}
总结:
static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。
final修饰的内容不可变,可以用于修饰类、方法和变量。
final修饰的类,不能被继承。
格式:
final class 类名 {
}
如:
final class Fu {
}
// class Zi extends Fu {} // 报错,不能继承final的类
final修饰的方法,不能被重写。
格式:
修饰符 final 返回值类型 方法名(参数列表){
//方法体
}
如:
class Fu2 {
final public void show1() {
System.out.println("Fu2 show1");
}
public void show2() {
System.out.println("Fu2 show2");
}
}
class Zi2 extends Fu2 {
// @Override
// public void show1() {
// System.out.println("Zi2 show1");
// }
@Override
public void show2() {
System.out.println("Zi2 show2");
}
}
变量的值不能修改
局部变量:
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。
public class FinalDemo1 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 10;
// 第二次赋值
a = 20; // 报错,不可重新赋值
// 声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值
b = 20; // 报错,不可重新赋值
}
}
成员变量:
成员变量涉及到初始化的问题,初始化方式有显示初始化和构造方法初始化,不能同时使用final修饰,只能选择其中一个:
显示初始化(在定义成员变量的时候赋值)
public class Student {
final int num = 10;
}
构造方法初始化(在构造方法中赋值一次)
//注意:每个构造方法中都要赋值一次!
public class Student {
final int num = 10;
final int num2;
public Student() {
this.num2 = 20;
// this.num2 = 20;
}
public Student(String name) {
this.num2 = 20;
// this.num2 = 20;
}
}
变量的地址值不能修改,内部属性值可以修改
final int[] ARR = {1,2,3,4,5};
//ARR = new int[10];
ARR[0] = 10;
ARR[1] = 20;
构造方法是一种特殊的方法
作用:创建对象的时候,由虚拟机自动调用,是给成员变量进行初始化的
格式:
public class 类名{
修饰符 类名( 参数 ) {
}
}
特点:
功能:主要是完成对象数据的初始化
例:
//学生类
class Student {
private String name;
private int age;
//空参构造
public Student() {}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
//有参构造
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println(name + "," + age);
}
}
//测试类
public class StudentDemo {
public static void main(String[] args) {
//创建对象
Student s1 = new Student();
s1.show();
//public Student(String name)
Student s2 = new Student("李逍遥");
s2.show();
//public Student(int age)
Student s3 = new Student(30);
s3.show();
//public Student(String name,int age)
Student s4 = new Student("李逍遥",30);
s4.show();
}
}
注意:
构造方法的创建
如果没有定义构造方法,系统将给出一个默认的无参数构造方法
如果定义了构造方法,系统将不再提供默认的构造方法
构造方法的重载
如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
可以使用带参构造,为成员变量进行初始化
① 类名需要见名知意
② 成员变量使用private修饰
③ 提供至少两个构造方法
④ get和set方法
提供每一个成员变量对应的setXxx()/getXxx()
⑤ 如果还有其他行为,也需要写上
API (Application Programming Interface) :应用程序编程接口
java中的API指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们可以直接使用这些类,但如何使用呢?那就要学习这些类的使用,通过帮助文档来学习这些API如何使用
帮助文档位置:
jdk帮助文档一般在jdk的docs目录下,可以用浏览器直接打开,每个API都有索引及用法说明
概念:
String 类代表字符串,Java 程序中的所有字符串文字(如"abc")都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。String 类在 java.lang 包下,所以使用的时候不需要导包
特点:
常用的构造方法
方法 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s = “abc”; | 直接赋值的方式创建字符串对象,内容就是abc |
例:
import java.util.Scanner;
public class StringDemo01 {
public static void main(String[] args) {
//public String():创建一个空白字符串对象,不含有任何内容
String s1 = new String();
System.out.println("s1:" + s1);
//public String(char[] chs):根据字符数组的内容,来创建字符串对象
char[] chs = {'a', 'b', 'c'};
String s2 = new String(chs);
System.out.println("s2:" + s2);
//public String(byte[] bys):根据字节数组的内容,来创建字符串对象
byte[] bys = {97, 98, 99};
String s3 = new String(bys);
System.out.println("s3:" + s3);
//String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc
String s4 = "abc";
System.out.println("s4:" + s4);
}
}
注意:
通过构造方法创建
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
直接赋值方式创建
以"abc"方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
**==**比较
比较基本数据类型时:比较的是具体的值
比较引用数据类型时:比较的是对象地址值
equals方法
比较两个字符串内容是否相同、区分大小写
import java.util.Scanner;
public class StringDemo02 {
public static void main(String[] args) {
//构造方法的方式得到对象
char[] chs = {'a', 'b', 'c'};
String s1 = new String(chs);
String s2 = new String(chs);
//直接赋值的方式得到对象
String s3 = "abc";
String s4 = "abc";
//比较字符串对象地址是否相同
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s3 == s4);
System.out.println("--------");
//比较字符串内容是否相同
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s3.equals(s4));
}
}
charAt():会根据索引获取对应的字符
import java.util.Scanner;
public class StringDemo03 {
public static void main(String[] args) {
//charAt():会根据索引获取对应的字符
//length(): 会返回字符串的长度
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串");
String str = sc.next();
//2.遍历
for (int i = 0; i < str.length(); i++) {
//i 依次表示字符串的每一个索引
//根据索引获取字符串里面的每一个字符
//ctrl + alt + V 自动生成左边的接受变量
char c = str.charAt(i);
System.out.println(c);
}
}
}
import java.util.Scanner;
public class StringDemo04 {
public static void main(String[] args) {
//键盘录入一个字符串,统计大写,小写,数字出现的次数
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.统计 --- 计数器count
//此时我要统计的有3样东西,所以要定义3个计数器分别进行统计
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
//得到这个字符串里面每一个字符
for (int i = 0; i < str.length(); i++) {
//i 表示字符串中的索引
//c 表示字符串中的每一个字符
char c = str.charAt(i);
//对c进行判断
if (c >= 'a' && c <= 'z') {
smallCount++;
} else if (c >= 'A' && c <= 'Z') {
bigCount++;
} else if (c >= '0' && c <= '9') {
numberCount++;
}
}
//3.当循环结束之后,三个变量记录的就是对应的个数
System.out.println("大写字符有:" + bigCount + "个");
System.out.println("小写字符有:" + smallCount + "个");
System.out.println("数字字符有:" + numberCount + "个");
}
}
import java.util.Scanner;
public class StringDemo05 {
public static void main(String[] args) {
/*定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,
并在控制台输出结果。例如,数组为 int[] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]*/
int[] arr = {1, 2, 3, 4, 5};
String str = arrToString(arr);
System.out.println(str);
}
//作用:把一个数组变成字符串
public static String arrToString(int[] arr) {
String s = "";
//拼接左括号
s = s + "["; //此时是拿着长度为0的字符串,跟[进行拼接,产生一个新的字符串。
//把新的字符串再赋值给s,此时变量s记录的就是新的字符串"["的地址值
//遍历数组,得到数组里面的每一个元素并进行拼接
for (int i = 0; i < arr.length; i++) {
//假设第一次循环:i = 0 获取的就是0索引上的元素
//在拼接的时候:"[" + 1 + ", " 拼接完毕之后产生一个新的字符串 "[1, "
//第二次循环:i = 1 获取的就是1索引上的元素
//在拼接的时候: 此时s就是第一次循环结束后拼接完毕的结果:"[1, "
//在拼接的时候:"[1, " + 2 + ", " 拼接完毕之后产生一个新的字符串 "[1, 2, "
//...
if (i == arr.length - 1) {
//如果是最后一个元素,那么不需要拼接逗号空格
s = s + arr[i];
} else {
//如果不是最后一个元素,需要拼接元素和逗号空格
s = s + arr[i] + ", ";
}
}
//等循环结束之后,再拼接最后一个右括号
s = s + "]";
return s;
}
}
import java.util.Scanner;
public class StringDemo06 {
public static void main(String[] args) {
/*定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
例如,键盘录入 abc,输出结果 cba*/
//1.定义一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.定义一个方法,反转字符串
//abc ---> cba
//可以把字符串倒着遍历,再拼接
String result = reverse(str);
System.out.println(result);
}
//把传递进来的字符串进行反转
public static String reverse(String str){//abc
//核心思想:倒着遍历并进行拼接就可以了
String s = "";
for (int i = str.length() - 1; i >= 0; i--) {
//我们就可以拿到里面的每一个字符并拼接
s = s + str.charAt(i);
}
return s;
}
}
把2135变成:零佰零拾零万贰仟壹佰叁拾伍元
把789变成:零佰零拾零万零仟柒佰捌拾玖元
import java.util.Scanner;
public class StringDemo03 {
public static void main(String[] args) {
//1.键盘录入一个金额
Scanner sc = new Scanner(System.in);
int money;
while (true) {
System.out.println("请录入一个金额");
money = sc.nextInt();
if (money >= 0 && money <= 9999999) {
break;
} else {
System.out.println("金额无效");
}
}
//定义一个变量用来表示钱的大写
String moneyStr = "";
//2.得到money里面的每一位数字,再转成中文
while (true) {
//从右往左获取数据,因为右侧是数据的个位
int ge = money % 10;
String capitalNumber = getCapitalNumber(ge);
//把转换之后的大写拼接到moneyStr当中
moneyStr = capitalNumber + moneyStr;
//第一次循环 : "伍" + "" = "伍"
//第二次循环 : "叁" + "伍" = "叁伍"
//去掉刚刚获取的数据
money = money / 10;
//如果数字上的每一位全部获取到了,那么money记录的就是0,此时循环结束
if (money == 0) {
break;
}
}
//3.在前面补0,补齐7位
int count = 7 - moneyStr.length();
for (int i = 0; i < count; i++) {
moneyStr = "零" + moneyStr;
}
System.out.println(moneyStr);//零零零贰壹叁伍
//4.插入单位
//定义一个数组表示单位
String[] arr = {"佰","拾","万","仟","佰","拾","元"};
// 零 零 零 贰 壹 叁 伍
//遍历moneyStr,依次得到 零 零 零 贰 壹 叁 伍
//然后把arr的单位插入进去
String result = "";
for (int i = 0; i < moneyStr.length(); i++) {
char c = moneyStr.charAt(i);
//把大写数字和单位拼接到result当中
result = result + c + arr[i];
}
//5.打印最终结果
System.out.println(result);
}
//定义一个方法把数字变成大写的中文
//1 -- 壹
public static String getCapitalNumber(int number) {
//定义数组,让数字跟大写的中文产生一个对应关系
String[] arr = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
//返回结果
return arr[number];
}
}
**substring()**方法
import java.util.Scanner;
public class StringDemo8 {
public static void main(String[] args) {
/*以字符串的形式从键盘接受一个手机号,隐藏中间四位号码
最终效果为:155****4568*/
//1.键盘录入一个手机号码
Scanner sc = new Scanner(System.in);
System.out.println("请输入手机号码");
String phoneNumber = sc.next();
//2.截取手机号码中的前三位
String star = phoneNumber.substring(0, 3);
//3.截取手机号码中的最后四位
//此时我用substring方法
//因为现在我们要截取到最后,第二个参数可以省略不写
String end = phoneNumber.substring(7);
//4.拼接
String result = star + "****" + end;
System.out.println(result);
}
}
**replace()**方法
import java.util.Scanner;
public class StringDemo09 {
public static void main(String[] args) {
/*以字符串的形式从键盘接受一个手机号,隐藏中间四位号码
最终效果为:155****4568*/
//1.键盘录入一个手机号码
Scanner sc = new Scanner(System.in);
System.out.println("请输入手机号码");
String phoneNumber = sc.next();
//2.截取手机号码中间四位
String star = phoneNumber.substring(3, 7);
//3.截取手机号码中的最后四位
//此时我用replace方法
//替换中间四位
String result = phoneNumber.replace(star, "****");
System.out.println(result);
}
}
StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。
当我们在拼接字符串和反转字符串的时候会使用到
append()添加元素 reverse()反转 toString()把StringBuilder变回字符串
例:
import java.util.Scanner;
public class StringDemo03 {
//键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
public static void main(String[] args) {
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.反转键盘录入的字符串
//创建对象,append:添加元素 reverse:反转 toString:把StringBuilder变回字符串
String result = new StringBuilder().append(str).reverse().toString();
//3.比较
if(str.equals(result)){
System.out.println("当前字符串是对称字符串");
}else{
System.out.println("当前字符串不是对称字符串");
}
}
}
注意:
因为StringBuilder是Java已经写好的类,java在底层对他做了一些特殊处理,使打印对象不是地址值而是属性值。
StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率,代码编写特别简洁
例:
import java.util.StringJoiner;
//定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果
public class StringJoiner0 {
public static void main(String[] args) {
//1.定义数组
int[] arr = {1, 2, 3};
//2.创建对象
StringJoiner sj = new StringJoiner(", ", "[", "]");
//3.添加元素
for (int i = 0; i < arr.length; i++) {
sj.add(arr[i] + "");
}
int len = sj.length();
System.out.println(len);
//4.打印
System.out.println(sj);
String str = sj.toString();
System.out.println(str);
}
}
概念:
集合是一种存储空间可变的存储模型,存储的数据容量可以发生改变,只能存储引用数据类型
若要存储基本数据类型得用对应的包装类
泛型:
约束集合中存储元素的数据类型
ArrayList array = new ArrayList(); //泛型<数据类型>
基本数据类型对应的包装类:
基本数据类型 | ArrayList包装类 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
方法名 | 说明 |
---|---|
public ArrayList() | 创建一个空的集合对象 |
方法名 | 说明 |
---|---|
public boolean add(要添加的元素) | 将指定的元素追加到此集合的末尾,返回值表示是否追加成功 |
public boolean remove(要删除的元素) | 删除指定元素,返回值表示是否删除成功 |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
例:
import java.util.ArrayList;
public class ArrayListDemo01 {
public static void main(String[] args) {
//创建集合
ArrayList<String> array = new ArrayList<String>();
//添加元素
array.add("hello");
array.add("小姐姐");
System.out.println(array.add("你好呀!"));
//删除指定的元素,返回删除是否成功
// System.out.println(array.remove("小姐姐"));
// System.out.println(array.remove("java"));
//删除指定索引处的元素,返回被删除的元素
// System.out.println(array.remove(1)); //该索引处若没有元素,则会报错
//修改指定索引处的元素,返回被修改的元素
// System.out.println(array.set(1, "黑丝小仙女")); //该索引处若没有元素,则会报错
//查找元素,返回指定索引处的元素
System.out.println(array.get(0));
System.out.println(array.get(1));
// System.out.println(array.get(5)); //该索引处若没有元素,则会报错
//获取元素长度,返回集合中的元素的个数
// System.out.println(array.size());
//输出集合
System.out.println("array:" + array);
}
}
概念:
继承是面向对象三大特征之一(封装,继承,多态)
继承就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
优点:
格式:
关键字 extends
,可以声明一个子类继承另外一个父类
class 父类 {
...
}
class 子类 extends 父类 {
...
}
注意:
并不是父类的所有内容都可以给子类继承的,子类不能继承父类的构造方法,但是是子类可以继承父类的私有成员(成员变量、方法),只是子类无法直接访问,可以通过getter/setter方法访问父类的private成员变量。
如果子类父类中出现重名的成员变量,子类会优先访问自己对象中的成员变量。
如果此时我们想访问父类中的成员变量如何解决呢?我们可以使用super关键字。修饰父类成员变量,类似于 this关键字。
super代表的是父类对象的引用,this代表的是当前对象的引用。
格式:
super.父类成员变量名
例:
class Fu {
// Fu中的成员变量。
int num = 5;
}
class Zi extends Fu {
// Zi中的成员变量
int num = 6;
public void show() {
int num = 1;
// 访问方法中的num
System.out.println("method num=" + num);//1
// 访问子类中的num
System.out.println("Zi num=" + this.num);//6
// 访问父类中的num
System.out.println("Fu num=" + super.num);//5
}
}
class Demo01 {
public static void main(String[] args) {
// 创建子类对象
Zi z = new Zi();
// 调用子类中的show方法
z.show();
}
}
注意:
Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。
概念:
子类中出现与父类重名的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
例:
class Fu {
public void show() {
System.out.println("Fu show");
}
}
class Zi extends Fu {
//子类重写了父类的show方法
@Override //注解,可以不写
public void show() {
System.out.println("Zi show");
}
}
public class Demo02{
public static void main(String[] args) {
Zi z = new Zi();
// 子类中有show方法,只执行重写后的show方法
z.show(); // Zi show
}
}
@Override重写注解:
@Override:注解,重写注解校验!
这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
可以省略
注意:
子类不能继承父类的构造方法
原因:
例:
class Person {
private String name;
private int age;
public Person() {
System.out.println("父类无参");
}
// getter/setter省略
}
class Student extends Person {
private int score;
public Student() {
//super(); // 调用父类无参,默认就存在,可以不写,必须在第一行
System.out.println("子类无参");
}
public Student(int score) {
//super(); // 调用父类无参,默认就存在,可以不写,必须在第一行
this.score = score;
System.out.println("子类有参");
}
}
public class Demo03 {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("------------");
Student s2 = new Student(0);
}
}
总结:
super和this的用法
关键字 | 成员变量 | 成员方法 | 构造方法 |
---|---|---|---|
this() | this.成员变量 访问本类成员变量 | this.成员方法名() 访问本类成员方法 | this(…) 访问本类构造方法 |
super() | super.成员变量 访问父类成员变量 | super.成员方法名() 访问父类成员变量 | super(…) 访问父类构造方法 |
注意:
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
super(…)和this(…)是根据参数去确定调用父类哪个构造方法的。
super(…)可以调用父类构造方法初始化继承自父类的成员变量的数据。
this(…)可以调用本类中的其他构造方法。
概念:
多态是面向对象三大特征之一(封装,继承,多态)
多态是指同一行为,具有多个不同表现形式。
多态是出现在继承或者实现关系中的。
多态的前提:
有继承或者实现关系
方法的重写【意义体现:不重写,无意义】
父类引用指向子类对象【格式体现】
格式:
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();
父类类型:指子类对象继承的父类类型,或者实现的父接口类型。
不用多态:
使用多态后,方法的形参就可以定义为共同的父类Person
注意:
调用成员变量时:编译看左边,运行看左边
调用成员方法时:编译看左边,运行看右边
Fu f = new Zi();
//编译看左边的父类中有没有name这个属性,没有就报错
//在实际运行的时候,把父类name属性的值打印出来
System.out.println(f.name);
//编译看左边的父类中有没有show这个方法,没有就报错
//在实际运行的时候,运行的是子类中的show方法
f.show();
多态编译阶段是看左边父类类型的,如果子类有些独有的功能,此时多态的写法就无法访问子类独有功能了。
class Animal{
public void eat(){
System.out.println("动物吃东西!")
}
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
}
class Test{
public static void main(String[] args){
// 向上转型
Animal a = new Cat();
a.eat();
a.catchMouse();//编译报错,编译看左边,Animal没有这个方法
//解决方案,向下转型
Cat c = (Cat)a;
c.catchMouse();
}
}
为什么转换呢?
就是为了解决多态的弊端:“多态的写法无法访问子类独有功能”
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有的,而父类没有的方法。那么想要调用子类特有的方法,必须做向下转型。
**向上转型:**多态本身就是子类类型向父类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
格式:
父类类型 变量名 = new 子类类型();
Animal a = new Cat();
**原因:父类类型相对与子类来说是大范围的类型,Animal是动物类,是父类类型。Cat是猫类,是子类类型。Animal类型的范围当然很大,包含一切动物。**所以子类范围小可以直接自动转型给父类类型的变量。
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
格式:
子类类型 变量名 = (子类类型) 父类变量名;
Aniaml a = new Cat();
Cat c =(Cat) a;
为了避免运行时ClassCastException的发生,Java提供了 instanceof
关键字,给引用变量做类型的校验
格式:
变量名 instanceof 数据类型
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false。
在转换前,我们可以先做一个判断,如:
public class Test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
// 向下转型
if (a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse(); // 调用的是 Cat 的 catchMouse
} else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse(); // 调用的是 Dog 的 watchHouse
}else{
System.out.println("没有这个类型,无法转换");
}
}
}
instanceof新特性:
JDK14的时候提出了新特性,把判断和强转合并成了一行
//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){
d.lookHome();
}else if(a instanceof Cat c){
c.catchMouse();
}else{
System.out.println("没有这个类型,无法转换");
}
父类知道子类应该有哪个功能,但是功能具体怎么实现父类是不清楚(由子类自己决定),父类只需要提供一个没有方法体的定义即可,具体实现交给子类自己去实现。我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。
用于修饰方法和类,修饰的方法是抽象方法,修饰的类是抽象类。
使用abstract
关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义:
修饰符 abstract 返回值类型 方法名 (参数列表);
public abstract void run();
注意:抽象方法的类必须定义成抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。
定义:
abstract class 类名字 {
}
public abstract class Animal {
public abstract void run();
}
例:
// 父类,抽象类
abstract class Employee {
private String id;
private String name;
private double salary;
public Employee() {
}
public Employee(String id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
// 抽象方法
// 抽象方法必须要放在抽象类中
abstract public void work();
}
// 定义一个子类继承抽象类
class Manager extends Employee {
public Manager() {
}
public Manager(String id, String name, double salary) {
super(id, name, salary);
}
// 2.重写父类的抽象方法
@Override
public void work() {
System.out.println("管理其他人");
}
}
// 定义一个子类继承抽象类
class Cook extends Employee {
public Cook() {
}
public Cook(String id, String name, double salary) {
super(id, name, salary);
}
@Override
public void work() {
System.out.println("圣美要快点找个女朋友哈!!!");
}
}
// 测试类
public class Demo10 {
public static void main(String[] args) {
// 创建抽象类,抽象类不能创建对象
// 假设抽象类让我们创建对象,里面的抽象方法没有方法体,无法执行.所以不让我们创建对象
// Employee e = new Employee();
// e.work();
// 3.创建子类
Manager m = new Manager();
m.work();
Cook c = new Cook("002", "圣美", 1);
c.work();
}
}
此时的方法重写,是子类对父类抽象方法的完成实现,也叫做实现方法。
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
抽象类存在的意义是为了被子类继承。
接口是更加彻底的抽象,JDK7之前,包括JDK7,接口中全部是抽象方法和常量。接口也是不能创建对象的。
定义:
//接口的定义格式:
interface 接口名称{
// 抽象方法
}
// 接口名称:首字母大写,满足“驼峰模式”
抽象方法:
接口中的抽象方法默认会自动加上public abstract修饰,可以不写
常量:
在接口中定义的成员变量默认会加上 public static final修饰。也就是说在接口中定义的成员变量实际上是一个常量。这里是使用public static final修饰后,变量值就不可被修改,并且是静态化的变量可以直接用接口名访问,所以也叫常量。常量必须要给初始值
public interface InterF {
// 抽象方法!
// public abstract void run();
void run();
// public abstract String getName();
String getName();
// public abstract int add(int a , int b);
int add(int a , int b);
// public static final int AGE = 10 ;
int AGE = 10; //常量
String SCHOOL_NAME = "黑马大学";
}
类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements
关键字。
格式:
/**接口的实现:
在Java中接口是被实现的,实现接口的类称为实现类。
实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{
}
要求:
意义:
接口体现的是一种规范,接口对实现类是一种强制性的约束,要么全部完成接口申明的功能,要么自己也定义成抽象类。这正是一种强制性的规范。
定义一个人的接口,如:
public interface PlayMan {
void run(); // 抽象方法,跑。
void eat(); // 抽象方法,吃。
String playgame(String game); // 抽象方法,打游戏
}
接下来定义一个"我"的类,实现接口,实现接口的实现类代码如下:
/**
* 接口的实现:
* 在Java中接口是被实现的,实现接口的类称为实现类。
* 实现类的格式:
* class 类名 implements 接口1,接口2,接口3...{
*
*
* }
* */
public class Mankind implements PlayMan {
@Override
public void run() {
System.out.println("圣美跑不动了");
}
@Override
public void eat() {
System.out.println("圣美想吃零食!!");
}
@Override
public String playgame(String game) {
return "圣美在玩"+game;
}
}
测试代码:
public class TestMain {
public static void main(String[] args) {
// 创建实现类对象。
Mankind m = new Mankind();
m.run();
m.eat();
System.out.println(m.playgame("王者荣耀"));
}
}
类与接口的多实现:
类与接口之间的关系是多实现的,一个类可以同时实现多个接口。
定义两个接口,如:
public interface Eat {
void eat();
}
public interface Run {
void run();
}
然后定义一个实现类:
/**
* Java中接口是可以被多实现的:
* 一个类可以实现多个接口: Eat, Run
* */
public class Mankind implements Eat ,Run {
@Override
public void eat() {
System.out.println("圣美想吃零食");
}
@Override
public void run() {
System.out.println("圣美跑不动了!");
}
}
Java中,接口与接口之间是可以多继承的:也就是一个接口可以同时继承多个接口。
接口继承接口就是把其他接口的抽象方法与本接口进行了合并。
如:
public interface Abc {
void go();
void test();
}
public interface Law {
void rule();
void test();
}
public interface SportMan extends Law , Abc {
void run();
}
概念:
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成寄生,外部类理解成宿主。
分类 | 类的位置 |
---|---|
成员内部类 | 类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类) |
静态内部类 | 类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类) |
局部内部类 | 类定义在方法内 |
匿名内部类 | 没有名字的内部类,可以在方法中,也可以在类中方法外 |
无static修饰的内部类,属于外部类对象的。
格式:
外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类
获取成员内部类对象的两种方式:
方式一:外部直接创建成员内部类的对象
外部类.内部类 变量 = new 外部类().new 内部类();
方式二:在外部类中定义一个方法提供内部类的对象
例:
方式一:
public class Test {
public static void main(String[] args) {
// 宿主:外部类对象。
// Outer out = new Outer();
// 创建内部类对象。
Outer.Inner oi = new Outer().new Inner();
oi.method();
}
}
class Outer {
// 成员内部类,属于外部类对象的。
// 拓展:成员内部类不能定义静态成员。
public class Inner{
// 这里面的东西与类是完全一样的。
public void method(){
System.out.println("内部类中的方法被调用了");
}
}
}
方式二:
public class Outer {
String name;
private class Inner{
static int a = 10;
}
public Inner getInstance(){
return new Inner();
}
}
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
System.out.println(o.getInstance());
}
}
注意:
格式:
外部类.内部类。
静态内部类创建对象的格式:
外部类.内部类 变量 = new 外部类.内部类构造器;
调用方法的格式:
//调用非静态方法的格式:
先创建对象.用对象调用;
//调用静态方法的格式:
外部类名.内部类名.方法名();
例:
// 外部类:Outer01
class Outer01{
private static String sc_name = "黑马";
// 内部类: Inner01
public static class Inner01{
// 这里面的东西与类是完全一样的。
private String name;
public Inner01(String name) {
this.name = name;
}
public void showName(){
System.out.println(this.name);
// 拓展:静态内部类可以直接访问外部类的静态成员。
System.out.println(sc_name);
}
}
}
public class InnerClassDemo01 {
public static void main(String[] args) {
// 创建静态内部类对象。
// 外部类.内部类 变量 = new 外部类.内部类构造器;
Outer01.Inner01 in = new Outer01.Inner01("圣美");
in.showName();
}
}
定义在方法中的类
格式:
class 外部类名 {
数据类型 变量名;
修饰符 返回值类型 方法名(参数列表) {
// …
class 内部类 {
// 成员变量
// 成员方法
}
}
}
匿名内部类是内部类的简化写法。他是一个隐藏了名字的内部类。
格式:
new 类名或者接口名() {
重写方法;
};
包含了:
继承或者实现关系
方法重写
创建对象
所以从语法上来讲,这个整体其实是匿名内部类的对象
如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用:是为了简化代码。
之前我们使用接口时:
interface Swim {
public abstract void swimming();
}
// 1. 定义接口的实现类
class Student implements Swim {
// 2. 重写抽象方法
@Override
public void swimming() {
System.out.println("潜泳式...");
}
}
public class Test {
public static void main(String[] args) {
// 3. 创建实现类对象
Student s = new Student();
// 4. 调用方法
s.swimming();
}
}
匿名内部类前提:
必须继承一个父类或者实现一个父接口。
格式:
new 父类名或者接口名(){
// 方法重写
@Override
public void method() {
// 执行语句
}
};
例:
interface Swim {
public abstract void swimming();
}
public class Demo03 {
public static void main(String[] args) {
// 使用匿名内部类
new Swim() {
@Override
public void swimming() {
System.out.println("自由泳...");
}
}.swimming();
// 接口 变量 = new 实现类(); // 多态,走子类的重写方法
Swim s2 = new Swim() {
@Override
public void swimming() {
System.out.println("潜泳式...");
}
};
s2.swimming();
s2.swimming();
}
}
扩展:
通常在方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递。如:
interface Swim {
public abstract void swimming();
}
public class Demo03 {
public static void main(String[] args) {
// 普通方式传入对象
// 创建实现类对象
Student s = new Student();
goSwimming(s);
// 匿名内部类使用场景:作为方法参数传递
Swim s3 = new Swim() {
@Override
public void swimming() {
System.out.println("蝶泳...");
}
};
// 传入匿名内部类
goSwimming(s3);
// 完美方案: 一步到位
goSwimming(new Swim() {
public void swimming() {
System.out.println("大学生, 潜泳...");
}
});
goSwimming(new Swim() {
public void swimming() {
System.out.println("小学生, 自由泳...");
}
});
}
// 定义一个方法,模拟请一些人去游泳
public static void goSwimming(Swim s) {
s.swimming();
}
}
希望我的笔记对你们有帮助,我喜欢你们的点赞,感谢、感谢!!!