Java基础入门
1.Java基础知识
1.1 环境说明
版本:Java 11.0
系统:windows
1.2 Java语言跨平台
- Java程序可以在任意的操作系统上运行。
- 跨平台原理:在需要运行Java应用程序的操作系统上,安装一个与操作系统对应的Java虚拟机(JVM Java Virtual Machine)即可。
1.3 JRE和JDK
- JRE(Java Runtime Environment),Java程序的运行时环境,包含JVM和运行时所需要的核心类库。
- JDK(Java Development Kit),Java程序开发工具包,包含JRE和开发人员使用的工具。
1.4 JDK的下载和安装
Java官网: https://www.oracle.com/java/technologies/downloads/
JDK的安装目录
目录名称 | 说明 |
---|---|
bin | 该路径下存放了JDK的各种工具命令,javac和java就放在这个目录。 |
conf | 该路径下存放了JDK的相关配置文件。 |
inclued | 该路径下存放了一些平台特定的头文件。 |
jmods | 该路径下存放了JDK的各种模块。 |
legal | 该路径下存放了JDK各模块的授权文档。 |
lib | 该路径下存放了JDK工具的一些补充JAR包。 |
2.第一个Java程序
2.1 设置环境变量
新建 JAVA_HOME 变量
编辑 Path 变量
执行命令,确认 JAVA 环境变量配置是否成功。
2.2 Hello World
开发Java程序,需要三个步骤:编写程序,编译程序,运行程序。
Java源代码
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
}
}
Java源码编译
# javac 文件名.java
# 生成 .class字节码文件
javac HelloWorld.java
Java程序运行
# java 类名
java HelloWorld
3.Java语法
3.1 注释
注释是在程序指定位置添加的说明性信息。
单行注释
// 注释信息
多行注释
/* 注释信息 */
文档注释
/** 注释信息 */
3.2 关键字
关键字:被Java语言赋予了特定含义的单词。
关键字的特点:(1)关键字的字母全部小写;(2)常用的代码编辑器,针对关键字有特殊的标识;
3.3 常量
常量:在程序运行过程中,其值不可以发生改变的量。
常量分类
常量类型 | 说明 | 举例 |
---|---|---|
字符串常量 | 用双括号括起来的内容 | "Hello World","黑马程序员" |
整数常量 | 不带小数的数字 | 666,-88 |
小数常量 | 带小数的数字 | 13.14,-5.21 |
字符常量 | 用单括号括起来的内容 | 'A','C','我' |
布尔常量 | 布尔值,表示真假 | 只有两个值:true、false |
空常量 | 一个特殊的值,空值 | 值是:null |
3.4 数据类型
计算机存储单元
计算机存储设备的最小信息单元叫“位(bit)”,又称之为比特位,通常用小写的字母“b”表示。而计算机中最小的存储单元叫“字节(byte)”,通常用大写字母“B”表示,字节是由连续的8个位组成。
常用的计算机存储单位
1B(字节)= 8bit
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
Java的数据类型
Java语言是强类型语言,对于每一种数据都给出了明确的数据类型,不同的数据类型也分配了不同的内存空间,所以它们表示的数据大小也是不一样的。
数据类型内存占用和取值范围
3.5 变量
变量:在程序运行过程中,其值可以发生改变的量。
从本质上讲,变量是内存中一小块区域。
变量定义
- 格式:数据类型 变量名 = 变量值;
- 示例:int a = 10;
代码使用
/*
变量格式定义:
数据类型 变量名 = 变量值;
基本数据类型:
byte,short,int,long,float,double,char,boolean
变量的使用:
取值格式:变量名
修改值格式:变量名 = 变量值;
*/
public class VariableBase {
public static void main(String[] args) {
// 定义变量
int a = 10;
// 输出变量
System.out.println(a);
// 修改变量
a = 20;
System.out.println(a);
}
}
过程中出现的问题:编译出现编码问题,如下图所示。
该问题是由于dos环境采用的GBK编码,只需要使用VScode或其他代码编辑工具,修改编码格式即可,修改前记得保存原注释,过程中可能会造成乱码。
再次运行,编译正常无报错。
变量的定义使用
/*
变量格式定义:
数据类型 变量名 = 变量值;
基本数据类型:
byte,short,int,long,float,double,char,boolean
变量的使用:
取值格式:变量名
修改值格式:变量名 = 变量值;
*/
public class VariableDemo {
public static void main(String[] args) {
// 定义byte类型的变量
byte b = 10;
System.out.println(b);
// 定义short类型的变量
short s = 100;
System.out.println(s);
// 定义int类型的变量
int i = 1000;
System.out.println(i);
// 定义double类型的变量
double d = 13.14;
System.out.println(d);
// 定义char类型的变量
char c = 'a';
System.out.println(c);
// 定义boolean类型的变量
// 变量b已经定义,不可以重复定义
boolean bb = true;
System.out.println(bb);
// 定义long类型的变量
// 给出一个整数,默认为int类型,需要在其后添加L标识为long类型
long l = 100000000000L;
System.out.println(l);
// 定义float类型的变量
// 给出一个小数,默认为double类型,需要在其后添加F标识为float类型
float f = 13.14F;
System.out.println(f);
}
}
变量使用的注意事项
- 变量名称不能够重复。
- 变量未赋值不能够使用。
- long、float类型需要在其后添加对应的标识说明。
3.6 标识符
标识符:给类、方法、变量等起名字的符号。
标识符定义规则
- 由数字、字母、下划线(_)和美元符($)组成。
- 不能以数字开头。
- 不能是关键字。
- 区分大小写。
3.7 类型转换
自动类型转换:把一个表示范围小的数值或者变量赋值给另一个表示数据范围大的变量。
示例:double d = 10;
强制类型转换:把一个表示数据范围大的数值或者变量赋值给另一个表述数据范围小的变量。
格式:目标数据类型 变量名 = (目标数据类型)值或者变量
示例:int i = 1.0
代码示例
/*
类型转换
*/
public class ConversionDemo {
public static void main(String [] args) {
// 自动类型转换
// int -> double
double d = 10;
System.out.println(d);
// 强制类型转换
// double -> int
int i = (int)d;
System.out.println(i);
}
}
3.8 运算符
运算符:对常量或者变量进行操作的符号。
表达式:用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式。
示例:
int a = 10;
int b = 20;
int c = a + b;
// + 是运算符,并且是算术运算符。
// a + b 是表达式,由于 + 是算术运算符,所以这个表达式叫算术表达式。
算术运算符
代码示例
/*
算数运算符
*/
public class OperatorDemo {
public static void main(String [] args) {
// 定义两个变量
int a = 6;
int b = 4;
System.out.println(a + b);
System.out.println(a - b);
System.out.println(a * b);
// 整数相除只能得到整数,要想得到小数,必须有浮点数的参与
System.out.println(a / b);
System.out.println(6.0 / 4);
System.out.println(a % b);
}
}
字符的“+”操作
字符的“+”操作是拿字符在计算机底层对应的数值来进行计算的。
/*
字符的"+"操作
*/
public class OperatorDemo2 {
public static void main(String [] args) {
// 定义两个变量
int i = 10;
// 字符 A 的值是 65
char c = 'A';
System.out.println(i + c);
// 字符 a 的值是 97
c = 'a';
System.out.println(i + c);
}
}
字符串的“+”操作
- 当“+”操作中出现字符串时,这个“+”是字符串连接符,而不是算术运算。
- 在“+”操作中,如果出现了字符串,就是连接运算符,否则就是算术运算,当连续进行“+”操作时,从左到右逐个执行。
代码示例:
/*
字符串的"+"操作
*/
public class OperatorDemo3 {
public static void main(String [] args) {
System.out.println("东北大学" + "(秦皇岛)");
// 结果是字符串
System.out.println("东北大学" + 666);
// 结果也是字符串
System.out.println(666 + "东北大学");
System.out.println("东北大学" + 6 + 66);
System.out.println(2023 - 1923 + "年东北大学");
}
}
3.8.1 赋值运算符
代码示例:
/*
赋值运算符
*/
public class OperatorDemo4 {
public static void main(String [] args) {
// 把10赋值给int类型的变量
int i = 10;
System.out.println("i:" + i);
// += 把左边和邮编的数据做加法操作,结果赋值给左边
i += 10;
System.out.println(i);
// 扩展的赋值运算符,如 += 隐含了强制类型转换
// getClass().getName()
short s = 10;
s += 10;
System.out.println(s);
}
}
3.8.2 自增自减运算符
自增运算符既可以放在变量的后边,也可以放在变量的前边。
单独使用时,自增运算符无论放在变量的前边还是后边,最终的结果是一样的。
参与操作时,如果放在变量的后边,先拿变量参与操作,后再进行自增自减操作。
参与操作时,如果放在变量的前边,先拿变量做自增或自减操作,后拿变量参与操作。
代码示例
/*
自增自减运算符
*/
public class OperatorDemo5 {
public static void main(String [] args) {
// 定义变量
int i = 10;
System.out.println("i:" + i);
// 单独使用
i++;
System.out.println(i);
++i;
System.out.println(i);
// 参与操作使用
int j = i++;
System.out.println("i:"+i);
System.out.println("j:"+j);
System.out.println(i);
int p = ++i;
System.out.println("p:"+p);
System.out.println("i:"+i);
}
}
3.8.3 关系运算符
代码示例
/*
关系运算符
*/
public class OperatorDemo6 {
public static void main(String [] args) {
// 定义变量
int a = 10;
int b = 20;
int c = 30;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(b > a);
System.out.println(c >= a);
System.out.println(a < b);
System.out.println(a <= b);
}
}
3.8.5 逻辑运算符
逻辑运算符是用来连接关系表达式的运算符,也可以直接连接布尔类型的常量或者变量。
代码示例:
/*
逻辑运算符
*/
public class OperatorDemo7 {
public static void main(String [] args) {
// 定义变量
int a = 10;
int b = 20;
int c = 30;
boolean bb = true;
System.out.println(a > b & bb);
System.out.println(a < b & bb);
System.out.println(!(a > b) & bb);
}
}
3.8.6 短路逻辑运算符
代码示例
/*
短路逻辑运算符
*/
public class OperatorDemo8 {
public static void main(String [] args) {
// 定义变量
int a = 10;
int b = 20;
int c = 10;
int d = 20;
System.out.println((a++) > 100 & (b++) > 100);
System.out.println("a:" + a);
System.out.println("b:" + b);
// 判断c++ > 100 为false,结论已经出现,则不再进行判断
System.out.println((c++) > 100 && (d++) > 100);
System.out.println("c:" + c);
System.out.println("d:" + d);
}
}
3.8.7 三元运算符
格式:关系表达式?表达式1:表达式2
示例:a>b?a:b
计算规则:首先计算关系表达式的值,如果为true,表达式1的值就是运算的结果,如果为false,表达式2的值就是运算的结果。
代码示例:
/*
三元运算符
*/
public class OperatorDemo9 {
public static void main(String [] args) {
// 定义变量
int a = 10;
int b = 20;
int c = a > b ? a : b;
System.out.println("c:"+c);
}
}
3.9 数据输入
Scanner使用的基本步骤:
导包
import java.util.Scanner; // 导包的动作必须出现在类定义的上方
创建对象
Scanner sc = new Scanner(System.in); // 上面这个格式里面,只有sc时变量名,可以修改,其余的都不允许变
接收数据
int i = sc.nextInt(); // 上面这个格式里面,只有i是变量名,可以修改,其余的都不允许变
代码示例:
/**
* 数据输入
*/
// 导包
import java.util.Scanner;
public class ScannerDemo {
public static void main(String [] args){
// 创建数据
Scanner sc = new Scanner(System.in);
// 接收数据
int x = sc.nextInt();
// 输出数据
System.out.println("x:"+x);
}
}
3.10 分支语句
3.10.1 流程控制
顺序结构
顺序结构是程序中最简单的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行。
3.10.2 分支结构
分支结构:if、switch
if 语句格式
if(关系表达式){
语句体;
}
if else语句格式
if(关系表达式){
语句体1;
}else{
语句体2;
}
if else if 语句格式
if(关系表达式1){
语句体1;
}else if(关系表达式2){
语句体2;
}else{
语句体3;
}
switch 语句格式
switch(表达式){
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
default:
语句体n;
break;
}
3.10.3 循环结构
for 循环语句
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
while 循环语句
while(条件判断语句){
循环体语句;
}
do...while 循环语句
do{
循环体语句;
}while(条件判断语句);
三种循环语句的区别
- for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
- do...while循环先执行依次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
for 和 while 的区别
- 条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
- 条件控制语句所控制的自增变量,对于while循环来说不归属于其语法结构,在while循环结束后,该变量还可以继续使用
3.11 Random
Random:用于产生一个随机数。
使用步骤:
导包
import java.util.Random; // 导包的动作必须出现在类定义的上方
创建对象
Random r = new Random(); // 上面这个格式里面,r是变量名,可以修改,其他的不允许修改
获取随机数
int number = r.nextInt(10); // 获取数据的范围:[0,10) // 上面这个格式里面,number是变量名,可以修改,其他的不允许修改
代码示例
/**
* Random
*/
// 导包
import java.util.Random;
public class RandomDemo {
public static void main(String [] args){
// 创建对象
Random r = new Random();
// 获取随机数
int number = r.nextInt(10);
// 输出数据
System.out.println("number:"+number);
}
}
4.IDEA
4.1 IDEA中Hello World
基本步骤:
创建一个空项目(JavaSE_Code)
创建一个新模块(idea_test)
在idea_test模块下的src下创建一个包(com.itheima)
在com.itheima包下新建一个类(HelloWorld)
在HelloWorld类中编写代码
在idea中执行程序
4.2 IDEA中项目结构
4.3 IDEA中内容辅助键和快捷键
4.3.1 内容辅助键
快速生成语句
// 快速生成main()方法:psvm,回车 // 快速生成输出语句:sout,回车
内容辅助键
// ctrl + alt + space(内容提示,代码补全等)
4.3.2 快捷键
注释
// 单行注释:选中代码,ctrl + / ,再来一次,就是取消 // 多行注释:选中代码,ctrl + shift + / ,再来一次,就是取消
格式化
// ctrl + alt + l
4.4 IDEA中模块操作
新增模块
删除模块
导入模块
后续操作,继续点击next即可。
5.数组
5.1 数组定义格式
数组:一种用于存储多个相同类型数据的存储模型。
数组的定义格式
// 格式一:数组类型[] 变量名
int[] arr;
// 格式二:数组类型 变量名[]
int arr[];
数组的动态初始化
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
// 格式:数据类型[] 变量名 = new 数据类型[数组长度];
int [] arr = new int[3];
代码示例:
package com.itheima_01;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
/*
左侧:
int:说明数组中的元素类型是int类型
[]:说明这是一个数组
arr:这是数组的名称
右侧:
new:为数组申请内存空间
int:说明数组中元素的类型是int类型
3:数组长度,其实就是数据中的元素格式
* */
}
}
数组静态初始化
静态初始化:初始化时指定每个元素的初始值,由系统决定数组长度。
// 格式:数据类型[] 变量名 = new 数据类型[] {数据1,数据2,......};
int [] arr = new int[]{1,2,3};
// 简化格式:数据类型[] 变量名 = {数据1,数据2,......};
int [] arr = {1,2,3};
代码示例
package com.itheima_01;
public class ArrayDemo2 {
public static void main(String[] args) {
// 定义数组
int[] arr1 = new int[]{1, 2, 3};
// 简化定义
int[] arr2 = {1, 2, 3};
// 输出数组
System.out.println(arr1);
System.out.println(arr2);
// 数组数组元素
System.out.println(arr1[2]);
System.out.println(arr2[1]);
}
}
5.2 数组元素访问
数组元素的方式方式
// 格式:数组名
数组元素的访问方式
// 格式:数组名[索引]
代码示例:
package com.itheima_01;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = new int[3];
/*
左侧:
int:说明数组中的元素类型是int类型
[]:说明这是一个数组
arr:这是数组的名称
右侧:
new:为数组申请内存空间
int:说明数组中元素的类型是int类型
3:数组长度,其实就是数据中的元素格式
* */
// 数组名
// 内存空间的地址值
System.out.println(arr); // [I@3b6eb2ec
// 数组元素
// 系统为数组分配了初始值 0
// 数组在初始化时,会为存储空间添加默认值
// 整数:默认为0
// 浮点数:默认为0.0
// 布尔值:默认为false
// 字符:默认值是空字符
// 引用数据类型:默认值是null
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
}
}
5.3 内存分配
Java程序在运行时,需要在内存中分配空间,为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
5.4 数组操作的常见问题
索引越界(ArrayIndexOutOfBoundsException):访问了数组中不存在的索引对应的元素,造成索引越界问题。
空指针异常(NullPointerException):访问的数组已经不再指向堆内存的数据,造成空指针异常。
5.5 数组常见操作
数组遍历
package com.itheima_01;
public class ArrayDemo4 {
public static void main(String[] args) {
// 数组定义
int[] arr = {11, 22, 33, 44, 55};
// 数组遍历
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
数组最值
package com.itheima_01;
public class ArrayDemo5 {
public static void main(String[] args) {
// 数组定义
int[] arr = {11, 22, 55, 66, 23, 33, 44};
// 获取数组的最大值,最小值
int max_value = 0;
int min_value = 100;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max_value) {
max_value = arr[i];
}
if (arr[i] < min_value) {
min_value = arr[i];
}
}
System.out.println("数组的最大值是:" + max_value);
System.out.println("数组的最小值是:" + min_value);
}
}
6.方法
方法:讲具有独立功能的代码块组织成一个整体,使其具有特殊功能的代码集。
注意:
- 方法必须先创建才可以使用,该过程成为方法定义。
- 方法创建后并不是直接运行的,需要手动使用后才执行,该过程称为方法调用。
6.1 方法的定义和调用
方法定义
// 格式
public static void 方法名(){
// 方法体
}
// 示例
public static void isEvenNumber(){
// 方法体
}
方法调用
// 格式
方法名()
// 示例
isEvenNumber()
代码示例
package com.itheima;
public class MethodDemo {
public static void main(String[] args) {
// 调用方法
isEvenNumber();
}
// 定义一个方法,在方法中定义一个变量,判断该数据是否是偶数
public static void isEvenNumber() {
// 定义变量
int number = 10;
// 判断该数据是否是偶数
if (number % 2 == 0) {
System.out.println("该数据是偶数");
} else {
System.out.println("该数据不是偶数");
}
}
}
6.2 带参数方法的定义和调用
方法定义
// 格式
public static void 方法名(参数){
// 方法体
}
// 示例
public static void 方法名(数据类型 变量名1,数据类型 变量名2,...){
// 方法体
}
方法调用
// 格式
方法名(变量名1/常量1,变量名2/常量2);
// 格式
getMaxNumber(5,6);
代码示例
/*
带参数的方法调用
* */
package com.itheima;
public class MethodDemo2 {
public static void main(String[] args) {
// 方法调用
getMaxNumber(5,6);
int number1 = 10;
int number2 = 20;
getMaxNumber(number1, number2);
}
// 方法定义
public static void getMaxNumber(int num1, int num2) {
int number = num1 > num2 ? num1 : num2;
System.out.println("较大的数是:" + number);
}
}
形参和实参
- 形参:方法定义中的参数。
- 实参:方法调用中的参数。
6.3 带返回值方法的定义和调用
方法定义
// 格式
public static 数据类型 方法名(参数){
return 数据;
}
// 示例
public static boolean isEvenNumber(int number){
return true;
}
// 注:方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则程序将报错
方法调用
// 格式
方法名(参数);
// 示例
isEvenNumber(5);
// 格式2
数据类型 变量名 = 方法名(参数);
// 示例2
boolean flag = isEvenNumber(5);
// 注意:方法的返回值通常会使用变量接收,否则该返回值将无意义。
代码示例
package com.itheima;
/*
带返回值的方法
* */
public class MethodDemo3 {
public static void main(String[] args) {
boolean flag1 = isEvenNumber(6);
System.out.println(flag1);
int number = 6;
boolean flag2 = isEvenNumber(number);
System.out.println(flag2);
}
// 方法定义
public static boolean isEvenNumber(int number){
if(number%2==0){
return true;
}else {
return false;
}
}
}
6.4 方法注意事项
方法不能嵌套定义
void表示无返回值,可以省略return,也可以单独书写return,后面不加数据。
6.5 方法重载
方法重载概述
方法重载指同一个类中定义的多个方法之间的关系,满足下列条件的多个方法相互构成重载。
- 多个方法在同一个类中。
- 多个方法具有相同的方法名。
- 多个方法的参数不相同,类型不同或者数量不同。
方法重载特点
- 重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式。
- 重载仅针对同一个类中方法的名称与参数进行识别,与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载。
代码示例
package com.itheima;
/*
方法重载:
多个方法在同一个类中
多个方法具有相同的方法名
多个方法的参数不相同,类型不同或者数量不同
* */
public class MethodDemo4 {
public static void main(String[] args) {
// 依次调用重载的方法
int i1 = 10;
int i2 = 20;
int i3 = 30;
double d1 = 10.0;
double d2 = 20.0;
int result1 = sum(i1, i2);
System.out.println(result1);
double result2 = sum(d1, d2);
System.out.println(result2);
int result3 = sum(i1, i2, i3);
System.out.println(result3);
}
// 需求1:求两个int类型数据和的方法
public static int sum(int number1, int number2) {
return number1 + number2;
}
// 需求2:求两个double类型数据和的方法
public static double sum(double number1, double number2) {
return number1 + number2;
}
// 需求3:求三个int类型数据和的方法
public static int sum(int number1, int number2, int number3) {
return number1 + number2 + number3;
}
}
6.6 方法的参数传递
基本类型:对于基本数据类型的参数,形式参数的改变,不影响实际参数的值。
代码示例
package com.itheima; /* 方法参数的传递-基本类型 * */ public class MethodDemo5 { public static void main(String[] args) { int number = 100; System.out.println("调用change方法前:"+number); change(number); System.out.println("调用change方法后:"+number); } public static void change(int number){ number = 200; } }
引用类型:对于引用类型的参数,形式参数的改变,影响实际参数的值。
代码示例
package com.itheima; /* 方法参数传递-引用类型 * */ public class MethodDemo6 { public static void main(String[] args) { int[] arr = {10,20,30}; System.out.println("调用change方法前:"+arr[1]); changeArray(arr); System.out.println("调用change方法后:"+arr[1]); } public static void changeArray(int [] arr){ arr[1] = 200; } }
7.类和对象
类:类是对现实生活中一类具有共同属性和行为的事务的抽象。
对象:是能够看的见摸得着的真实存在的实体。
类的特点:
- 类是对象的数据类型。
- 类是具有相同属性和行为的一组对象的集合。
7.1 类的定义
类的重要性:是Java程序的基本组成单位。
类:是对现实生活中一类具有共同属性和行为的事物的抽象,确定对象将会拥有的属性和行为。
类的组成:属性和行为。
- 属性:在类中通过成员变量来体现(类中方法外的变量)。
- 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)。
Java中类的定义
public class 类名{
// 成员变量
变量1的数据类型 变量1;
变量2的数据类型 变量2;
// 成员方法
方法1;
方法2;
}
代码测试
package com.itheima;
public class Phone {
// 成员变量
String brand;
int price;
// 成员方法
public void call(){
System.out.println("打电话");
}
public void sendMessage(){
System.out.println("发短信");
}
}
7.2 对象的使用
代码测试
package com.itheima;
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 = "OPPO";
p.price = 6999;
System.out.println(p.brand);
System.out.println(p.price);
// 使用成员方法
p.call();
p.sendMessage();
}
}
7.3 成员变量和局部变量
- 成员变量:类中方法外的变量。
- 局部变量:方法中的便变量。
成员变量和局部变量区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 类中方法外 | 方法内或者方法声明上 |
内存中位置不同 | 堆内存 | 栈内存 |
声明周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的调用完毕而消失 |
初始化值不同 | 有默认的初始值 | 没有默认的初始值,必须先定义,赋值,才能使用 |
7.4 封装
7.4.1 private 关键字
private 关键字的说明:
- 是一个权限修饰符。
- 可以修饰成员(成员变量和成员方法)。
- 作用是保护成员不被别的类使用,被 private 修饰的成员只在本类中才能访问。
针对 private 修饰的成员变量,如果需要被其他类使用,提供相应的操作:
- 提供
get变量名()
方法,用于获取成员变量的值,方法用public
修饰。 - 提供
set变量名(参数)
方法,用于设置成员变量的值,方法用public
修饰。
private 关键字主要是为了应对非法的调用,保证数据的安全性,示例如下:
// 定义java类
package com.privateDemo;
public class Student {
// 成员变量
String name;
int age;
// 成员方法
public void show(){
System.out.println(name + ":" + age);
}
}
调用该对象,并修改其成员属性,如下所示:
package com.privateDemo;
public class StudentDemo {
public static void main(String[] args) {
// 创建变量
Student s = new Student();
// 调用成员方法
s.show();
// 修改成员变量
s.name = "南歌EuanSu";
s.age = -18;
s.show();
}
}
打印内容如下所示,即使 -18
并不是一个合法的年龄值,但是仍然被修改了,private 关键字就能够应对这些非法赋值,修改如上的类定义和调用方法。
类的定义修改如下所示
package com.privateDemo;
public class Student {
// 成员变量
String name;
private int age;
// 提供set/get方法
public void setAge(int number){
if(number < 0 || number > 120){
System.out.println("输入的年龄信息有误");
}else{
age = number;
}
}
public int getAge() {
return age;
}
// 成员方法
public void show(){
System.out.println(name + ":" + age);
}
}
类的方法调用修改如下所示
package com.privateDemo;
public class StudentDemo {
public static void main(String[] args) {
// 创建变量
Student s = new Student();
// 调用成员方法
s.show();
// 修改成员变量
s.name = "南歌EuanSu";
s.setAge(-18);
s.getAge();
s.setAge(18);
s.getAge();
// s.age = -18;
s.show();
}
}
运行代码,输出结果如下所示
7.4.2 this 关键字
- this 修饰的变量用于指代成员变量
- 方法的形参如果与成员变量同名,不带 this 修饰的变量指的是形参,而不是成员变量
- 方法的形参没有与成员变量同名,不带 this 修饰的变量指的是成员变量。
- 使用 this 关键字主要是为了解决局部变量与成员变量相同的场景
- this 代表所在类的方法引用
- 方法被那个对象调用,this 就代编哪个对象
这里先来示范一下局部变量与成员变量相同的场景,类的定义如下
package com.thisDemo;
public class Student {
private String Name;
private int Age;
// 提供set/get方法
public void setName(String Name){
Name = Name;
}
public String getName(){
return Name;
}
public void setAge(int Age){
if(Age < 0 || Age > 120){
System.out.println("输入的年龄信息有误");
}else{
Age = Age;
}
}
public int getAge() {
return Age;
}
public void show(){
System.out.println(Name + ":" + Age);
}
}
对象的调用如下
package com.thisDemo;
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
s.show();
s.setName("南歌EuanSu");
s.setAge(18);
s.show();
}
}
执行如上代码,输出的结果如下,并没有能够成功修改对象属性。
修改类的成员变量,主要是局部变量与成员变量同名的方法,如下所示:
public void setName(String Name){
this.Name = Name;
}
public void setAge(int Age){
if(Age < 0 || Age > 120){
System.out.println("输入的年龄信息有误");
}else{
this.Age = Age;
}
}
再次执行对象的调用,成功修改对象的成员属性。
7.4.3 总结
- 封装概述
- 是面向对象的三大特征之一(封装、集成、多态)
- 是面向对象编程语言对客观世界的模拟,客观世界成员变量都是隐藏在对象内部的,外界是无法直接操作的
- 封装原则
- 将类的某些信息隐藏在类内部,不允许外部程序直接方法,而是通过该类提供的方法来实现对隐藏信息的操作和方法
- 成员变量 private,提供对应的 getXxx()、setXxx()方法
- 封装的优点
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
7.5 构造方法
7.5.1 构造方法概述
构造方法是一种特殊的方法,作用是创建对象,主要是完成对象数据的初始化。
public class 类名{
修饰符 类名(参数){
}
}
一个无参的构造方法如下所示:
package com.constructDemo;
public class Student {
private String Name;
private int Age;
// 构造方法
public Student(){
System.out.println("无参数构造方法");
}
public void show(){
System.out.println(Name + ":" + Age);
}
}
编写方法创建该对象的实例,如下所示
package com.constructDemo;
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
}
}
输出如下
7.5.2 构造方法的注意事项
- 构造方法的创建
- 如果没有定义构造方法,系统将给出一个默认的无参数构造方法
- 如果定义了构造方法,系统将不再提供默认的构造方法
- 构造方法的重载
- 如果自定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法
- 推荐的使用方式
- 无论是否使用,都需要写一个无参数的构造方法
如下是一个代码示例,提供了构造方法。
package com.constructDemo2;
public class Student {
private String Name;
private int Age;
// 构造方法
public Student(String Name){
this.Name = Name;
}
public void show(){
System.out.println(Name + ":" + Age);
}
}
当调用该类时,必须要给出 Name 的值,否则会报如下错误。
要解决这个错误有两种方法:传入构造方法所需的 Name 值;手写一个无参数的构造方法。
传入 Name 值,修改调用该对象的方法如下:
package com.constructDemo2; public class StudentDemo { public static void main(String[] args) { Student s = new Student("南歌EuanSu"); s.show(); } }
再次执行对象的调用方法,不报错。
手写一个无参数的构造方法,修改该对象的初始化方法如下:
package com.constructDemo2; public class Student { ... public Student(){ } // 构造方法 public Student(String Name){ this.Name = Name; } ... }
调用该对象,分别传入 Name 值和不传入值,均能够成功将对象进行初始化。
除此之外,构造方法还能够实现不同值的初始化,修改对象的定义方法如下:
package com.constructDemo2;
public class Student {
private String Name;
private int Age;
public Student(){
}
// 构造方法
public Student(String Name){
this.Name = Name;
}
public Student(int Age){
this.Age = Age;
}
...
}
调用对象的初始化方法,不传值、传入 Name值、传入Age值,均能够成功进行对象的初始化。
7.5.3 标准类的制作
成员变量
- 使用 private 修饰
构造方法
- 提供一个无参构造方法
- 提供一个待多个参数的构造方法
成员方法
- 提供每一个成员变量对应的 setXxx()、getXxx()
- 提供一个显示对象信息的show()
创建对象并为其成员变量复制的两种法师
- 无参构造方法创建对象后使用 setXxx() 赋值
- 使用带参数构造方法直接创建带有属性的对象
一个标准类的定义如下所示
package com.standardClass;
public class Student {
private String Name;
private int Age;
// set/get 方法
public void setName(String Name) {
this.Name = Name;
}
public void setAge(int Age) {
this.Age = Age;
}
public int getAge() {
return Age;
}
public String getName() {
return Name;
}
// 构造方法
public Student(){}
public Student(String Name,int Age){
this.Name = Name;
this.Age = Age;
}
public void show(){
System.out.println(Name + ":" + Age);
}
}
一个标准类的调用如下
package com.standardClass;
public class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
s.setName("南歌EuanSu");
s.setAge(18);
s.show();
Student s2 = new Student("西野七濑", 27);
s2.show();
}
}
执行后,输出结果为