文章目录
1、Java语言发展史
2、Java语言跨平台原理
3、JRE和JDK
3.1、JRE(Java Runtime Environment)
- 是Java程序的运行时环境,包含JVM和运行时所需要的核心类库。
- 想运行一个已有的Java程序,只需安装JRE即可。
3.2、JDK(Java Development Kit)
- 是Java程序开发工具包,包含JRE和开发人员使用的工具。
- 其中的开发工具:编译工具(javac.exe)和运行工具(java.exe)。
- 想开发一个全新的Java程序,必须安装JDK。
3.3、JDK、JRE和JVM的关系
4、JDK的下载和安装
4.1、JDK的下载
- 通过官方网站获取JDK:https://www.oracle.com/downloads/
- 华为云各版本高速下载通道:https://repo.huaweicloud.com/java/jdk/
- 注意:针对不同操作系统,下载对应的JDK。
4.2、JDK的安装
- 安装路径中不要包含中文和空格。所有的开发工具最好安装目录统一。
4.3、JDK的安装目录
目录名称 | 说明 |
---|---|
bin | 该路径下存放了JDK的各种工具命令,常用的javac、java等命令就放在该路径下 |
conf | 存放了JDK的相关配置文件 |
include | 一些平台特定的头文件 |
jmods | 存放了JDK的各种模块 |
legal | JDK各模块的授权文档 |
lib | JDK工具的一些补充JAR包 |
其余为说明性文档。
4.4、Path环境变量的配置
- 为了开发Java程序时,能够方便使用Javac和Java这些命令,需配置Path环境变量。
- 配置
JAVA_HOME
- 配置
Path
系统环境变量
4、HelloWorld案例
-
编写HelloWorld.java
public class HelloWorld{ public static void main(String[] args){ System.out.print("Hello World!"); } }
-
编译:javac 文件名.java
-
执行:java 类名
5、基本语法
5.1、注释
- 单行注释
格式://注释信息
- 多行注释
格式:/*注释信息*/
- 文档注释
格式:/**注释信息*/
5.2、关键字
- 关键字的字母全部小写。
5.3、常量
5.3.1、常量概述
- 在程序运行过程中,其值不可以发生改变的量。
5.3.2、常量分类
常量类型 | 说明 | 举例 |
---|---|---|
字符串常量 | 用双引号括起来的内容 | “HelloWorld” |
整数常量 | 不带小数的数字 | 666 |
小数常量 | 带小数的数字 | 1.23 |
字符常量 | 用单引号括起来的内容 | ‘a’、'我' |
布尔常量 | 布尔值,表真假 | 只有两个值:true,false |
空常量 | 一个特殊的值,空值 | 值是:null |
注:空常量不能直接输出。
5.4、数据类型
5.4.1、计算机存储单元
- 位(bit):计算机存储设备的最小信息单元,也称比特位。通常用小写字母b表示。
- 字节(byte):计算机中最小的存储单元。通常用大定字母B表示。
5.4.2、数据类型
5.4.3、数据类型内存占用和取值范围
数据类型 | 关键字 | 内存占用 | 取值范围 |
---|---|---|---|
整数 | byte | 1 | -128~127 |
整数 | short | 2 | -32768~32767 |
整数 | int | 4 | -231 ~ 231 -1 |
整数 | long | 8 | -263 ~ 263 -1 |
浮点数 | float | 4 | 负数:-3.40283E+38到-1.401298E-45 正数:1.401298E-45到3.402823E+38 |
浮点数 | double | 8 | 负数:-1.797693E+308到-4.9000000E-324 正数:4.9000000E-324到1.797693E+308 |
字符 | char | 2 | 0~65535 |
布尔 | boolean | 1 | true,false |
5.5、变量
5.5.1、变量使用的注意事项
- 名字不能重复。
- 变量未赋值不能使用。
- long类型的变量定义的时候,为了防止整数过大,后面要加L。
- float类型的变量定义的时候,为了防止类型不兼容,后面要加F。
5.6、标识符
5.6.1、标识符定义规则
- 由数字、字母、
_
、$
组成。 - 不能以数字开头。
- 不能是关键字。
- 区分大小写。
5.6.2、常见命名约定
小驼峰命名法: 方法、变量
- 标识符是一个单词时,首字母小写
- 标识符由多个单词组成时,第一个单词首字母小写,其它单词首字母大写。如:
firstName
。
大驼峰命名法: 类
- 标识符是一个单词时,首字母大写
- 标识符由多个单词组成时,每个单词首字母大写。
5.7、类型转换
5.7.1、类型转换分类
- 自动类型转换
- 强制类型转换
5.7.2、自动类型转换
- 把一个表示数据范围小的数值或者变量赋值给另一个表示范围大的变量。
如:double=10;
表示数据范围从小到大图
注:不可以将byte直接赋值给char数据类型
5.7.3、强制类型转换
- 把一个表示数据范围大的数值或者变量赋值给另一个表示范围小的变量。
- 格式:目标数据类型 变量名=(目标数据类型)值或者变量;
- 如:
int a=(int)88.88;
6、运算符
6.1、算术运算符
6.1.1、算术运算符
符号 | 作用 | 说明 |
---|---|---|
+ | 加 | |
- | 减 | |
* | 乘 | |
/ | 除 | 两数做除法取结果的商。 整数操作只能得到整数,要想得到小数,必须有浮点数参与运算。 |
% | 取余 | 取结果的余数 |
6.1.2、字符的“+”操作
字符在计算机底层对应的值
- ‘A’ 对应的值是65
- 'a’对应的值是 97
- ‘0’ 对应的值是48
算术表达式中包含多个基本数据类型的值时,整个算术表达式的类型会自动进行提升。
提升规则:
- byte、short和char将被提升到int。
- 整个表达式的类型自动提升到表达式中最高等级操作数同样的类型
6.1.3、字符串的“+”操作
- “+”操作中出现字符串时,是字符串连接符,而不是算术运算。
“Hello”+666 - 连续 “+”操作时,从左到右逐个执行
1+99+“Hello” //结果是100Hello
“Hello”+1+99 //结果是Hello199
6.2、赋值运算符
=
+=
short s;
s+=1;//正确
s=s+1;//错误,s+1会被系统强转成int
s=(short)(s+1);//正确
-=
*=
/=
%=
注意:扩展的赋值运算符隐含了强制转换。
6.3、自增自减运算符
++
--
6.4、关系运算符
==
!=
>
>=
<
<=
6.5、逻辑运算符
6.5.1、基本逻辑运算符
符号 | 作用 | 说明 |
---|---|---|
& | 逻辑与 | a&b ,a和b都是true,结果为true,否则为false |
| | 逻辑或 | a|b ,a和b都是false,结果为false,否则为true |
^ | 逻辑异或 | a^b ,a和b结果不同为true,相同为false |
! | 逻辑非 |
6.5.1、短路逻辑运算符
符号 | 作用 | 说明 |
---|---|---|
&& | 短路与 | 作用和& 相同,但是具有短路效果 |
|| | 短路或 | 作用和| 相同,但是具有短路效果 |
注意事项:
- 逻辑与
&
,无论左边真假,右边都要执行。 - 短路与
&&
,若左边为假,右边不执行。 - 逻辑或
|
,无论左边真假,右边都要执行。 - 短路或
||
,如果左边为真,右边不执行。
6.6、三元运算符
- 如:
a>b?a:b;
- 计算规则:
若值为true,运算结果为a
若值为false,运算结果为b
7、数据输入
7.1、Scanner使用的基本步骤
import java.util.Scanner;
public class ScannerDemo{
public static void main(String[] args){
System.out.println("请输入一个整数:")
Scanner sc=new Scanner(System.in);
int x=sc.nextInt();
System.out.println("x="+x);
}
}
8、分支语句
8.1、流程控制
8.1.1、流程控制语句分类
-
顺序结构
-
分支结构
-
循环结构
8.2、if语句
格式1:
if(关系表达式){
语句体;
}
格式2:
if(关系表达式){
语句体;
}else{
语句体;
}
格式3:
if(关系表达式){
语句体;
}else if(关系表达式){
语句体;
}
else{
语句体;
}
8.3、switch语句
8.3.1、switch语句格式
格式:
switch(表达式){
case 值1:
语句体;
break;
case 值2:
语句体;
break;
... ...
default:
语句体;
break; //最后一个break可以省略
}
格式说明:
- 表达式:取值为byte、short、int、char
JDK5以后可以是枚举。
JDK7以后可以是String。 - case:后面跟的是要和表达式进行比较的值。
- break:表示中断,用来结束switch语句。
- default:表示所有情况都不匹配时,执行该处内容。
8.3.2、case穿透
- 在switch语句中,如果case控制的语句体后面不写break,将出现穿透现象。在不判断下一个case值的情况下,向下运行直到遇到break,或者整体switch语句结束。
import java.util.Scanner;
public class SwitchTest{
public static void main(String[] argss){
Scanner sc=new Scanner(System.in);
int month=sc.nextInt();
switch(month){
case 1:
case 2:
case 3:
System.out.println("春");
break;
case 4:
case 5:
case 6:
System.out.println("夏");
break;
case 7:
case 8:
case 9:
System.out.println("秋");
break;
case 10:
case 11:
case 12:
System.out.println("冬");
break;
default:
System.out.println("输入的月份有误");
}
}
}
9、循环语句
循环结构的组成:
- 初始化语句
- 条件判断语句
- 循环语句
- 条件控件语句
9.1、for循环语句
格式:
for(初始化语句;条件判断语句;条件控制语句){
循环语句;
}
for死循环格式:
for(;;){
}
水仙花数案例:
/**
什么是水仙花数
水仙花数是一个三位数
水仙花数的个位、十位、百位的数字立方和等于原数
*/
public class ForTest{
public static void main(String[] args){
for(int i=100;i<1000;i++){
int a=i%10; //个位上的数
int b=i/10%10; //十位上的数
int c=i/100; //百位上的数
if(a*a*a+b*b*b+c*c*c==i)
System.out.println(i);
}
}
}
9.2、while循环语句
格式:
初始化语句;
while(条件判断语句){
循环体语句;
条件控件语句;
}
while死循环格式:
while(true){
循环语句体;
}
9.3、do…while循环语句
格式:
初始化语句;
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
do…while死循环格式:
do{
循环语句体;
}while(true);
流程图
示例:
public class DoWhileDemo{
public static void main(String[] args){
int i=0;
do{
System.out.println("Hello world!");
i++;
}while(i<5);
}
}
9.4、控制跳转语句
continue
跳过某次循环体内容的执行,继续下一次的执行。break
终止循环内容的执行,结束当前的整个循环。
9.5、循环嵌套
9.6、Random
9.6.1、Random的作用和使用步骤
作用:产生一个随机数。
import java.util.Random;
public class RandomDemo{
public static void main(String[] args){
Random r=new Random();
for(int i=0;i<10;i++){
int number=r.nextInt(10);//获取的范围:[0,10)
System.out.println(number);
}
}
}
9.6.2、Random获取任意范围之间的随机数
r.nextInt(10); //获取的范围:[0,10)
r.nextInt(10)*5+10; //获取的范围:[10,60)
10、IDEA概述和安装
10.1、IDEA概述
- IDEA全称IntelliJ IDEA,用于Java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。
IDEA的下载地址:https://www.jetbrains.com/idea/
JDK9以后将不再支持32位的支持。
11、数组
- 数组(array)是一种用于存储多个相同类型数据的存储模型
11.1、数组定义格式
-
格式一: 数据类型[] 变量名
例:int[] arr
定义了一个int类型的数组,数组名是arr -
格式二: 数据类型 arr[]
例:int arr[]
定义了一个int类型的变量,变量名是arr数组 -
推荐使用格式一
11.2、数组动态初始化
-
Java中的数组必须先初始化,才能使用。
-
动态初始化: 初始化时只指定数组长度,由系统分配初始值。
-
数组初始化时,会为存储空间添加默认值
整数:
默认值0
浮点数:
默认值0.0
布尔值:
默认值false
字符:
默认值是空字符
引用数据类型:
默认值是null
-
格式:数据类型[] 变量名=new 数据类型[数组长度]
-
如:
int[] arr=new int[3]
11.3、数组元素访问
- 数组变量访问方式:数组名
- 数组元素访问方式:数组名[索引]
int[] arr=new int[3];
System.out.println(arr);//[I@1e643faf
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
11.4、内存分配
- 栈内存:存储局部变量,使用完毕,立即消失。例如:arr。
- 堆内存:存储new出来的内容(实体、对象)。
- 数组初始化时,会为存储空间添加默认值
整数:
默认值0
浮点数:
默认值0.0
布尔值:
默认值false
字符:
默认值是空字符
引用数据类型:
默认值是null
每一个new出来的东西都有一个地址值,使用完毕,会在垃圾回收器空闲时回收。
- 数组初始化时,会为存储空间添加默认值
11.5、数组静态初始化
- 静态初始化: 初始化时指定每个数组元素的初始值,由系统决定长度。
格式:数据类型[] 变量名=new 数据类型[] {数据1,数据2,数据3,......}
如:int[] arr=new int[]{1,2,3};
简化格式:int[] arr={1,2,3};
11.6、数组操作的两个常见小问题
- 索引越界: 访问了数组中不存在的索引对应的元素,造成索引越界问题。
- 空指针异常: 访问的数组已经不再指向堆内存的数据,造成空指针异常。
- null: 空值,引用数据类型的默认值,表示不指向任何有效对象。
11.7、数组常见操作
11.7.1、遍历
11.7.2、获取数组元素数量
int[] arr={1,2,3,4,5};
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
11.7.3、获取最值
int[] arr={2,1,6,5,9,8};
int max=arr[0];
for(int i=1;i<arr.length;i++){
if(max<arr[i])
max=arr[i];
}
System.out.println(max);
12、方法
12.1、方法的概述
12.2、方法的定义和调用
//方法定义
public static void 方法名(){
方法体;
}
12.3、带参数方法的定义和调用
- 形参:方法中定义的参数。
- 实参:方法调用中的参数。
12.4、带返回值方法的定义和调用
public static 数据类型 方法名(参数){
return 数据;
}
12.5、方法的注意事项
- 方法不能嵌套定义
- void表示无返回值,可以省略return,也可以单独的书写return,后面不加数据。
12.6、方法重载
满足下列条件的多个方法相互构成重载:
- 多个方法在同一个类中。
- 多个方法具有相同的方法名。
- 多个方法的参数不相同,类型不同或者数量不同。
12.7、方法的参数传递
传递引用 类型:
public class HelloWorld {
public static void main(String[] args){
int[] arr={10,20,30};
change(arr);
System.out.println(arr[1]);
}
public static void change(int[] arr){
arr[1]=100;
}
}
13、Debug
13.1、Debug概述
- Debug:是供程序员使用的程序调试工具,它可用于查看程序的执行流程,也可用于追踪程序执行过程来调试程序。
13.2、Debug操作流程
Debug调试,又称断点调试。
14、面向对象基础
14.1、类和对象
14.1.1、类的定义
类的组成:属性和行为。
属性:在类中通过成员变量来体现。
行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)。
14.2、对象内存图
14.3、成员变量和局部变量
成员变量和局部变量的区别
14.4、封装
14.4.1、private关键字
- 是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 被private修饰的成员只在本类中才能访问。
14.4.2、this关键字
- this修饰的变量用于指代成员变量
- this代表所在类的对象引用。方法被哪个对象调用,this就代表哪个对象。
14.4.3、封装
面向对象三大特征:封装、继承、多态。
封装好处:提高了代码的安全性;提高了代码复用率。
14.5、构造方法
14.5.1、构造方法注意事项
- 如果没有定义构造方法,系统将给出一个默认的无参构造方法。
- 如果定义了构造方法,系统将不再提供默认的构造方法。
- 无论是否使用,都手工书写无参构造方法。
14.5.2、标准类制作
成员变量
- 使用private修饰
构造方法
- 提供一个无参构造方法
- 提供一个带多个参数的构造方法
创建对象并为其成员变量赋值的两种方式
- 无参构造方法创建对象后使用用setXxx()赋值。
- 使用带参构造方法直接创建带有属性值的对象。
15、字符串
15.1、API
API(Application Programming Interface):应用程序编程接口。
15.2、String
- String类在java.lang包下,所以使用时不需要导包。
字符串特点:
- 字符串不可变,它们的值在创建后不能被更改。
- 虽然String的值是不可变的,但是它们可以被共享。
- 字符串效果上相当于字符串数组(
char[]
),但是底层原理是字节数组(byte[]
)。 - JDK8及以前是字符数组,JDK9以后是字节数组。
15.2.1、字符串构造方法
方法名 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s="abc" | 直接赋值的方式创建字符串对象,内容就是abc |
15.2.2、String对象的特点
-
通过new创建的字符串对象,每一次都会申请一个内存空间,虽然内容相同,但地址不同。
char[] chs={'a','b','c'}; String s1=new String(chs); String s2=new String(chs);
-
以“”方式给出的字符串,只要字符序列相同,JVM都只会建立一个String对象,并在字符串池中维护。
String s1="abc"; String s2="abc";
15.2.3、字符串的比较
使用==做比较:
- 基本类型:比较的是数据值是否相同。
- 引用类型:比较的是地址值 是否相同。
字符串是对象,比较内容相同,用equals()
public boolean equals(Object anObject)
:将此字符串与指定对象比较。由于我们比较字符串对象,所以参数传一个字符串。
15.2.4、遍历字符串
import java.util.Scanner;
public class StringTest {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个字符串");
String line=sc.nextLine();
for(int i=0;i<line.length();i++){
System.out.println(line.charAt(i));
}
}
}
15.2.5、统计字符出现次数
import java.util.Scanner;
public class StringTest01 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
int upperCount=0;
int lowCount=0;
int numberCount=0;
for(int i=0;i<line.length();i++){
char ch=line.charAt(i);
if(ch>='a' && ch<='z'){
upperCount++;
continue;
}
if(ch>='A' && ch<='Z'){
lowCount++;
continue;
}
if(ch>='0' && ch<='9'){
numberCount++;
continue;
}
}
System.out.println("大写字母"+upperCount+"个");
System.out.println("小写字母"+lowCount+"个");
System.out.println("数字"+numberCount+"个");
}
}
15.2.6、字符串反转
import java.util.Scanner;
public class StringTest02 {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
System.out.println("输入一个字符串:");
String line=sc.nextLine();
String s=reverse(line);
System.out.println(s);
}
public static String reverse(String s){
String ss="";
for(int i=s.length()-1;i>=0;i--){
ss+=s.charAt(i);
}
return ss;
}
}
15.3、StringBuilder
15.3.1、StringBuilder概述
- 如果字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费内存空间,而这种操作又不可避免。StringBuilder类用来解决这个问题。
- StringBuilder是一个可变的字符串类,可以把它看成是一个容器,这里的可变指的是StringBuilder对象中的内容是可变的。
String和StringBuilder的区别:
- String:内容是不可变的。
- StringBuilder:内容是可变的。
15.3.2、StringBuilder的添加和反转方法
public StringBuilder append(任意类型)
添加数据,并返回对象本身。public StringBuilder reverse()
返回相反的字符序列。
StringBuilder字符串拼接示例
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append("Hello").append(100);
System.out.println(sb);//输出Hello100
}
}
StringBuilder字符串反转示例
public class StringBuilderTest {
public static void main(String[] args) {
StringBuilder sb=new StringBuilder();
sb.append("Hello");
sb.reverse();
System.out.println(sb);//输出olleH
}
}
15.3.3、StringBuilder和String相互转换
一、StringBuilder转换为String:
调用StringBuilder的toString()
方法
二、String转换为StringBuilder:
public StringBuilder(String s)
通过构造方法可以把String转换为StringBuilder。
16、集合
16.1、集合基础
16.1.1、集合概述
- 如果要存储多个数据,使用长度固定的数组存储格式,不一定满足需求。
- 集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变。
ArrayList<E>
:
- 可调整大小的数组实现。
- :是一种特殊的数据类型,泛型。
16.1.2、ArrayList构造方法和添加方法
public ArrayList()
创建一个空的集合对象。
public boolean add(E e)
将指定的元素追加到此集合的末尾。
public void add(int index,E element)
在此集合中的指定位置插入指定的元素
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args){
//ArrayList<String> array=new ArrarList<>();//jdk7开始支持这种格式
ArrayList<String> array=new ArrayList<String>();
array.add("Hello");//集合中增加一个元素
array.add("World");
array.add(1,"aa");
System.out.println(array);
}
}
16.1.3、ArrayList集合常用方法
public boolean remove(Object o)
删除指定元素,返回删除是否成功
public E remove(int index)
删除指定索引处的元素,返回被删除的元素
public E set(int index,E element)
修改指定索引处的元素,返回被修改的元素
public E get(int index)
返回指定索引处的元素
public int size()
返回集合中的元素个数
17、继承
17.1、继承概述
继承格式:
public class 子类名 extends 父类名{}
如:
public class Dog extends Animal{
}
17.2、继承的优缺点
优点:
- 提高了代码的复用性
- 提高了代码的可维护性
缺点:
- 继承让类与类之间产生了关填信息,增强了类的耦合性,当父类发生变化时子类也不得不跟着变化,削弱了子类的独立性。
17.3、继承中变量的访问特点
子类方法中问题变量:
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 如果都没有就报错
17.4、supper
supper关键字的用法与this关键字的用法相似:
this
:代表本类对象的引用super
:代表父类对象的引用
关键字 | 访问成员变量 | 访问构造方法 | 访问成员方法 |
---|---|---|---|
this | 访问本类成员变量 | 访问本类构造方法this();//访问本类中无参构造方法,访问有参构造方法传参即可。 | 访问本类成员方法 |
super | 访问父类成员变量 | 访问父类构造方法super();//访问父类无参构造方法,访问有参构造方法传参即可。 | 访问父类成员方法 |
17.5、继承中构造方法的访问特点
- 子类中所有的构造方法默认都会访问父类中无参的构造方法。
为什么呢? - 因为子类会继承父类中的数据,可能还会使用父类的数据。所以子类初始化前,一定先完成父类数据的初始化。
- 每一个子类构造方法的第一条语句默认都是:
super()
如果父类中没有无参构造方法,只有带参构造方法:
- 通过使用super关键字显示调用父类的带参构造方法
- 在父类中自己提供一个无参构造方法。
- 推荐:自己给出无参构造方法。
17.6、继承中成员方法的访问特点
通过子类对象访问方法:
- 子类成员范围找
- 父类成员范围找
- 都没有就报错。
17.7、super内存图
17.8、方法重写
@Override
的作用
@Override
是伪代码,所以是可写可不写的.它表示方法重写,写上会给我们带来好处.- 可以当注释用,方便阅读.
- 告诉阅读你代码的人,这是方法的复写.
- 编译器可以给你验证
@Override
下面的方法名是否是你父类中所有的,如果没有则报错.
方法重写注意事项
- 私有方法不能被重写(父类私有成员子类是不能继承的)
- 子类方法访问权限不能更低(public>默认>私有)。
18、修饰符
18.1、包
18.1.1、包的概述
- 其实就是文件夹。
- 作用:对类进行分类管理。
包的定义格式:
格式:package 包名;
(多级包用.分开)
如:package com.chuhe;
18.1.2、带包的Java类编译和执行
一、手动建包
-
有HelloWorld.java在如下位置
//HelloWorld.java package com.chuhe; public class HelloWorld{ public static void main(String[] args){ System.out.println("HelloWorld"); } }
-
手动建包:按照以前的格式编译java文件。
-
手动创建包,并把编译好的class文件放入包中
-
带包执行
二、自动建包
javac -d . HelloWorld.java
18.2、导包
- 使用不同包下的类时,需写类的全路径,为简化带包的操作,Java提供了导包功能。
导包的格式:
格式:import 包名;
如:import com.chuhe.HelloWorld;
18.3、修饰符
18.3.1、修饰符的分类
- 权限修饰符。
- 状态修饰符。
18.3.2、权限修饰符
修饰符 | 同一个类中 | 同一包中子类、无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
18.3.3、状态修饰符
final
最终态static
静态
18.3.3.1、final
final
关键字是最终的意思,可修饰成员方法,成员变量,类
final修饰符的特点
- 修饰方法:表明该方法是最终方法,
不能被子类重写
。 - 修饰变量:表明该变量是常量,
不能再次被赋值
。 - 修饰类:表明该类是最终类,
不能被继承
。
final修饰局部变量
- final修饰的局部变量是基本类型:基本类型的数据值不能发生改变
- final修饰的局部变量是引用类型:引用类型的地址值不能发生改变,但地址里面的内容可以改变。
18.3.3.2、static
- static关键字可修饰成员方法,成员变量
- 被类的所有对象共享。
- 可以通过类名调用。
- 也可以通过对象名调用。
- 推荐使用类名调用。
static访问特点
非静态的成员方法:
- 能访问静态的成员变量。
- 能访问非静态的成员变量。
- 能访问静态的成员方法。
- 能访问非静态的成员方法。
静态的成员方法:
- 能访问静态的成员变量。
- 能访问静态的成员方法。
总结:静态成员方法只能访问静态成员。
19、多态
19.1、多态概述
同一对象,在不同时刻表现出来的不同形态。
- 有继承/实现关系
- 有方法重写
- 父类引用指向子类对象。
19.2、多态中成员的访问
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
因为成员方法有重写,而成员变量没有。
19.3、多态的好处和弊端
- 多态的好处:提高了程序的扩展性。
- 多态的弊端:不能使用子类的特有功能。
19.4、多态中的转型
- 向上转型
- 从子到父
- 从父类引用指向子类对象
- 向下转型
- 从父到子
- 父类引用转为子类对象
示例:
Animal a=new Cat();//向上转型
a.eat();
Cat c=(Cat)a;//向下转型,解决了多态的弊端
c.eat();
20、抽象类
- 抽象方法:没有方法体的方法。
- 抽象类:类中有抽象方法,该类必须定义为抽象类。
20.1、抽象类的特点
-
抽象类和抽象方法必须使用abstract关键字修饰
public abstract class Animal{ public abstract void eat(); }
-
抽象类可以没有抽象方法,有抽象方法的类一定是抽象类。
-
抽象类不能实例化。
参照多态的方式,通过子类对象的实例化,这叫抽象类多态。 -
抽象类的子类:
要么重写抽象类中的所有抽象方法。
要么是抽象类。
20.2、抽象类的成员特点
- 成员变量
可以是变量
也可以是常量 - 构造方法
有构造方法,但不能实例化
用于子类访问父类数据的初始化。 - 成员方法
可以有抽象方法:限定子类必须完成某些动作。
也可以有非抽象方法:提高代码复用性。
21、接口
21.1、接口概述
- 接口是一种公共的规范标准,只要符合规范标准,都可通用。
- Java中的接口更多的体现在对行为的抽象。
21.2、接口的特点
-
接口用关键字
interface
修饰public interface 接口名{ }
-
类实现接口用implements表示
public class 类名 implements 接口名{ }
-
接口不能实例化
参照多态的方式,通过实现类对象实例化,这叫接口多态。
多态的形式:具体类多态,抽象类多态,接口多态
多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象 -
接口的实现类
要么重写接口中的所有抽象方法
要么是抽象类
21.3、接口的成员特点
-
成员变量
只能是常量
默认修饰符:public static finalpublic interface Inter{ //接口中成员变量,默认修饰符:public static final //下面三个变量修饰符均相同 public int a=10; public final int b=20 public static final int c=30 }
-
构造方法
接口没有构造方法,因为接口主要是对行为进行抽象的,没有具体存在。
一个类如果没有父类,默认继承自Object类。
接口实现类名后习惯加Impl
。public class InterImpl implements Inter{ }
等价于
public class InterImpl extends Object implements Inter{ }
-
成员方法
只能是抽象方法
默认修饰符:public abstractpublic interface Inter{ void f1();//前面默认修饰符public abstract public abstract f2(); }
关于接口中的方法,JDK8和JDK9中有一些新特性,暂且不表。
21.4、类和接口的关填信息
-
类和类的关系
继承关系,只能单继承,但是可以多层继承。 -
类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。public class InterImpl extends Object implements Inter1,Inter2,Inter3{ }
-
接口和接口的关系
继承关系,可以单继承,也可以多继承。public interface Inter3 extends Inter1,Inter2{ }
21.5、抽象类和接口的区别
成员区别
- 抽象类:变量,常量;有构造方法;有抽象方法,也有非抽象方法
- 接口:常量;抽象方法
关系区别
- 类与类:继承关系,单继承
- 类与接口:实现关系,可以单实现,也可以多实现
- 接口与接口:继承关系,单继承,多继承
设计理念区别:
- 抽象类:对类抽象,包括属性、行为
- 接口:对行为抽象,主要是行为。
示例:
门和警报的例子,门:都有open()和close()两个动作,
使用抽象类定义这个抽象概念
//抽象类
public abstract class Door{
public abstract void open();
public abstract void close();
public abstract void alarm();
}
使用接口定义这个抽象概念
public interface Door{
void open();
void close();
void alarm();
}
如果门不具备报警功能,上述抽象类和接口都不适用。
最优实现方式:
//接口抽象动作
public interface Alram{
void alam();
}
//抽象类抽象属性、行为
public abstract class Door{
public abstract void open();
public abstract void close();
}
//并不是所有的门都具有报警功能
//有报警功能就实现报警接口
public class AlarmDoor extends Door implements Alarm{
public void open(){...}
public void close(){...};
public void alarm(){...};
}
22、形参和返回值
22.1、类名做为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象。
- 方法的返回值是类名,其实返回的是该类的对象。
22.2、抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象。
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象。
22.3、接口名做为形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象。
- 方法的返回值是接口名,其实返回的是该接口的实现类对象。
23、内部类
23.1、内部类的概述
- 就是在一个类中定义一个类。
- 类A的内部定义一个类B,类B就被称为内部类。
内部类的定义格式
public class 类名{
修饰符 class 类名{
}
}
如:
public class Outer{
public class Inner{
}
}
23.2、内部类的访问特点
- 内部类可直接访问外部类的成员,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
public class Outer {
private int num=0;
public class Inner{
public void show(){
System.out.println(num);
}
}
public void method(){
Inner i=new Inner();
i.show();
}
}
23.3、成员内部类
按照内部类在类中定义的位置不同,可分为如下两种形式:
- 在类的成员位置:成员内部类。
- 在类的局部位置(如方法中):局部内部类。
成员内部类
public class Outer {
private int num=0;
public class Inner{
public void show(){
System.out.println(num);
}
}
public void method(){
Inner i=new Inner();
i.show();
}
}
外界创建成员内部类对象:
- 只有内部类类用public修饰,才允许在外界创建,只允许在外部类中使用。
- 一般内部类都用private修饰,起到隐藏作用。
格式:外部类名.内部类名 对象名=外部类对象.内部类对象;
如:Outer.Inner oi=new Outer().new Inner();
23.4、局部内部类
- 局部内部类是在方法中定义的类,所以外界无法直接使用。
- 需要在方法内部创建对象并使用。
- 该类可直接访问外部类的成员,也可访问方法内的局部变量。
public class Outer {
private int num=0;
public void method(){
//局部内部类
class Inner{
public void show(){
System.out.println(num);
}
}
Inner i=new Inner();
i.show();
}
}
23.5、匿名内部类
- 也是一种局部内部类。
- 前提:存在一个类或者接口,这里的类可以是具体的类也可是抽象类。
格式 :
new 类名或者接口名(){
重写方法;
};
如:
new Inter(){
public void show(){
}
};//这里要加分号
本质:是一个继承了该类或者实现了该类接口的子类匿名对象。
//接口
public interface Inter {
void show();
}
//Outer类
public class Outer {
public void method(){
Inter i=new Inter(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
}
}
23.5、匿名内部类在开发中的使用
Jumpping.java
//Jumpping接口
public interface Jumpping {
void jump();
}
JumppingOperator.java
public class JumppingOperator {
//形参为Jumpping,即传入Jumpping接口的实现
public void method(Jumpping j){
j.jump();
}
}
JumppingDemo.java
public class JummpingDemo {
public static void main(String[] args) {
JumppingOperator jo=new JumppingOperator();
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
});
}
}