Java语言入门到精通章节
笔记小结:
- 定义:Java是一种高级语言。它被设计为一种通用的、面向对象的编程语言,具有跨平台性和可移植性
- 特点:简单易学、面向对象编程、平台无关性、安全性、高性能、多线程支持、开源免费
- 跨平台原理:针对于不同的操作系统,Java提供了不同的虚拟机,对于不同的操作系统,安装不同的虚拟机
- 三大版本:
- JavaSE:SE即标准版,包含了Java核心类库,主要用来开发桌面应用
- JavaME:ME即微型版,包含了SE中部分类库,又有自己扩展部分,主要用来做移动类嵌入式开发
- JavaEE:EE即企业版,包含SE,又有扩展部分(Servlet,JDBC等),主要用来开发分布式网络程序
- JRE、JVM、JDK:
- JVM(Java Virtual Machine),Java虚拟机
- JRE(Java Runtime Environment),Java运行环境,包含了JVM和Java的核心类库(Java API)
- JDK(Java Development Kit)称为Java开发工具,包含了JRE和开发工具
- 下载和安装
- 目录介绍
- 环境变量配置
Java是一种广泛使用的计算机编程语言,由Sun Microsystems(后来被Oracle收购)在1995年推出。它被设计为一种通用的、面向对象的编程语言,具有跨平台性和可移植性
补充:
语言:人与人交流沟通的表达方式
计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言
Java语言跨平台的原理
JavaSE、JavaME、JavaEE
JavaSE(Java Platform, Standard Edition),Java语言的(标准版),用于桌面应用的开发,是其他两个版本的基础。
JavaME(Java Platform, Micro Edition),Java语言的小型版,用于嵌入式消费类电子设备或者小型移动设备的开发。(嵌入式,电视机,微波炉,电视机等),其中最为主要的还是小型移动设备的开发(手机)。渐渐的没落了,已经被安卓和IOS给替代了。但是,安卓也是可以用Java来开发的。
JavaEE(Java Platform, Enterprise Edition)用于Web方向的网站开发。(主要从事后台服务器的开发)在服务器领域,Java是当之无愧的龙头老大。
说明:
当我们开发时,我们只需安装JDK即可,它包含了java的运行环境和虚拟机。当我们只运行时只需要装JRE即可
说明:
通过官方网站获取JDK,网址:Java Downloads | Oracle 中国
注意:
- 安装路径不要有中文,不要有空格等一些特殊的符号。
- 以后跟开发相关的所有软件建议都安装在同一个文件夹中,方便管理。
补充:安装目录
- 以上是JDK17的安装目录,以下是JDK的目录解释
目录名称 说明 bin 该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。 conf 该路径下存放了JDK的相关配置文件。 include 该路径下存放了一些平台特定的头文件。 jmods 该路径下存放了JDK的各种模块。 legal 该路径下存放了JDK各模块的授权文档。 lib 该路径下存放了JDK工具的一些补充JAR包。
步骤二:环境变量配置
说明:
开发Java程序,需要使用JDK提供的开发工具(比如javac.exe、java.exe等命令),而这些工具在JDK的安装目录的bin目录下,如果不配置环境变量,那么这些命令只可以在bin目录下使用,而我们想要在任意目录下都能使用,所以就要配置环境变量
1.配置JAVA_HOME
环境
2.配置PATH
环境
补充:
- JAVA_HOME:告诉操作系统JDK安装在了哪个位置(未来其他技术要通过这个找JDK)
- Path:告诉操作系统JDK提供的javac(编译)、java(执行)命令安装到了哪个位置
步骤三:演示
java --version
说明:
此处可以看到JDK的版本为17
笔记小结:
Java程序开发运行流程需要三个步骤:编写程序,编译程序,运行程序
说明:
通过
HelloWorld
程序演示Java流程基本执行流程
步骤一:创建Java程序
HelloWorld.class
文件,并编写class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
步骤二:编译Java程序
说明:
javac
是 Java 编译器的命令行工具,用于将 Java 源代码文件(以.java
扩展名结尾)编译成 Java 字节码文件(以.class
扩展名结尾)。Java 字节码文件可以在Java虚拟机(JVM)上运行。
javac
命令javac HelloWorld.java
说明:结果
步骤三:执行字节码文件
java
命令java HelloWorld
说明:结果
注意:
运行class文件时,不需要加
.class
后缀
笔记小结:
注释:单行注释、多行注释、文档注释
关键字:
- 定义:被Java赋予了特定含义的英文单词
- class、static、……
字面量:
- 定义:数据在程序中的书写格式
- 666、”MySoul“、……
变量:
- 定义:临时存储数据的容器
- int a = 16;、double b = 10.1;、……
- 注意:Java中变量需要有变量类型、变量名以及分号结束
数据类型:
- 基本数据类型:byte、short、int、long、float、double、char和boolean
- 引用数据类型:字符串、数组、类和接口、……
- 区别:
- 基本数据类型存储在栈中,而引用数据类型存储在堆中
- 基本数据类型的变量之间是相互独立的,而引用数据类型的变量之间可能共享同一个对象
标识符:
- 定义:标识符是用来命名变量、方法、类、接口等程序元素的名称
- 注意:
- 必须由数字、字母、**下划线_、美元符号$**组成。
- 数字不能开头
- 不能是关键字
- 区分大小写的
- 阿里巴巴命名规范细节
权限修饰符:
- 定义:权限修饰符是Java中的一种关键字,用于控制类、方法和变量的访问权限
- 权限范围:
private
<默认/空着不写
<protected
<public
包:
定义:包是一种用于组织和管理 Java 类的机制
命名规范:
路径名.路径名.xxx.xxx // 例如:com.itheima.oa
导包:不是在java.lang包下,都需要导包。因为Java开发环境,默认为lang包
注释是对代码的解释和说明文字
Java中的注释分为三种:
// 这是单行注释文字
/*
这是多行注释文字
这是多行注释文字
这是多行注释文字
*/
注意:
多行注释不能嵌套使用!
/**
这是多行注释文字
这是多行注释文字
这是多行注释文字
*/
说明:使用的技巧
- 如果我们要对代码进行解释,那么就可以使用注释
- 当注释的内容比较少,一行就写完了,可以用单行注释
- 如果注释的内容比较多,需要写在多行,那么可以使用多行注释
Java关键字就是被Java赋予了特定含义的英文单词。当我们在代码中写了关键字之后,程序在运行的时候,就知道要做什么事情了。
Java 关键字是编程语言中预定义的具有特殊含义的词汇,这些关键字用于控制程序的结构、流程和行为
注意
关键字很多,不用刻意去记
public
、protected
、private
、static
、final
、abstract
public
、protected
、private
、default
(默认)class
、interface
、enum
、package
、import
、extends
、implements
void
、return
、this
、super
if
、else
、switch
、case
、default
、while
、do
、for
、break
、continue
、return
try
、catch
、finally
、throw
、throws
true
、false
、null
new
、instanceof
、synchronized
、transient
、volatile
、assert
Class
类此关键字表示定义一个类public class HelloWorld{
}
说明:
解释:class表示定义类
类名:HelloWorld
HelloWorld后面的大括号表示这个类的范围
Java 字面量是程序中直接使用的常量值,它表示各种数据类型的固定值。字面量可以是整数、浮点数、字符、字符串等数据类型的常量值,它们在代码中直接出现,不需要进行计算或转换。
42
, 012
, 0xFF
。3.14
, 2.0e-5
。'A'
, '1'
, '@'
。"Hello, World!"
, "Java"
。true
和 false
。\
开头,用于表示无法直接输入的字符,如换行符 \n
、制表符 \t
等。{}
表示,用于初始化数组。例如:{1, 2, 3}
。\u
开头,后面跟着四个十六进制数字。例如:\u0041
表示字符 ‘A’。public class Demo {
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("欢迎来到黑马程序员"); // 输出字符串
}
}
补充:区分技巧
- 不带小数点的数字都是整数类型的字面量
- 只要带了小数点,那么就是小数类型的字面量
- 只要用双引号引起来的,不管里面的内容是什么,不管里面有没有内容,都是字符串类型的字面量。
- 字符类型的字面量必须用单引号引起来,不管内容是什么,但是个数有且只能有一个
- 布尔类型的字面量只有两个值,true、false
- 空类型的字面量只有一个值,null
变量就在程序中临时存储数据的容器。但是这个容器中只能存一个值。
数据类型 变量名 = 数据值;
说明:
如果要存10,那么数据类型就需要写整数类型。
如果要存10.0,那么数据类型就需要写小数类型。
补充:参数解释
变量名:其实就是这个容器的名字
数据值:真正存储在容器中的数据
分号:表示语句的结束,就跟以前写作文时候的句号是一样的
public class VariableDemo2{
public static void main(String[] args){
//1.变量名不允许重复
//int a = 10;
//int a = 20;
//System.out.println(a);
//2.一条语句可以定义多个变量
//了解。
//int a = 10, b = 20, c = 20,d = 20;
//System.out.println(a);//?
//System.out.println(b);//?
//3.变量在使用之前必须要赋值
int a = 30;
System.out.println(a);
}
}
注意:
- 变量名不能重复
- 在一条语句中,可以定义多个变量。但是这种方式影响代码的阅读,所以了解一下即可。
- 变量在使用之前必须要赋值。
Java 数据类型是用来定义变量或表达式可以存储的数据类型的分类
byte
:8位,范围为 -128 到 127、short
:16位,范围为 -32,768 到 32,767、int
:32位,范围为 -2^31 到 2^31 - 1、long
:64位,范围为 -2^63 到 2^63 - 1float
:32位,用于表示单精度浮点数、double
:64位,用于表示双精度浮点数char
:16位,用于存储一个 Unicode 字符boolean
:用于表示布尔值,只有两个取值:true
和 false
注意:
- byte类型的取值范围: -128 ~ 127
- int类型的大概取值范围: -21亿多 ~ 21亿多
补充:整数类型和小数类型的取值范围大小关系:
- double > float > long > int > short > byte
- 在java中整数默认是int类型,浮点数默认是double类型
代码示例:
public class VariableDemo3{
public static void main(String[] args){
//1.定义byte类型的变量
//数据类型 变量名 = 数据值;
byte a = 10;
System.out.println(a);
//2.定义short类型的变量
short b = 20;
System.out.println(b);
//3.定义int类型的变量
int c = 30;
System.out.println(c);
//4.定义long类型的变量
long d = 123456789123456789L;
System.out.println(d);
//5.定义float类型的变量
float e = 10.1F;
System.out.println(e);
//6.定义double类型的变量
double f = 20.3;
System.out.println(f);
//7.定义char类型的变量
char g = 'a';
System.out.println(g);
//8.定义boolean类型的变量
boolean h = true;
System.out.println(h);
}
}
注意:
- 如果要定义 一个整数类型的变量,不知道选择哪种数据类型了,默认使用int。
- 如果要定义 一个小数类型的变量,不知道选择哪种数据类型了,默认使用double。
- 如果要定义一个long类型的变量,那么在数据值的后面需要加上L后缀。(大小写都可以,建议大写。)
- 如果要定义一个float类型的变量,那么在数据值的后面需要加上F后缀。(大小写都可以)
补充:
详细请参考知识加油站站
基本数据类型和引用数据类型区别
代码示例:
// 使用引用数据类型创建一个对象
String message = new String("Hello, World!");
// 创建一个数组
int[] numbers = new int[5];
// 使用自定义类创建对象
class Person {
String name;
int age;
}
Person person = new Person();
person.name = "Alice";
person.age = 30;
// 枚举类型
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Day today = Day.WEDNESDAY;
代码示例:
public class VariableDemo{
public static void main(String[] args){
//定义一个整数类型的变量
//数据类型 变量名 = 数据值;
int a = 16;
System.out.println(a);//16
//定义一个小数类型的变量
double b = 10.1;
System.out.println(b);//10.1
}
}
补充:
null不能直接打印的,如果需要打印需要用字符串的形式进行打印。
最为常用的数据类型选择:
在定义变量的时候,要根据实际的情况来选择不同类型的变量。
比如:人的年龄,可以选择byte类型
比如:地球的年龄,可以选择long类型
如果整数类型中,不太确定范围,那么默认使用int类型
如果小数类型中,不太确定范围,那么默认使用double类型
如果要定义字符类型的变量,那么使用char
如果要定义布尔类型的变量,那么使用boolean
在Java中,标识符是用来标识程序中各种元素的名称,比如变量、方法、类、接口等。标识符是由字母、数字、下划线(_)和美元符号($)组成的序列,且必须以字母、下划线或美元符号开头。标识符在编程中用于命名各种实体,使得程序易于阅读、理解和维护
必须要这么做,否则代码会报错。
1.小驼峰命名法
适用于变量名和方法名
如果是一个单词,那么全部小写,比如:name
如果是多个单词,那么从第二个单词开始,首字母大写,比如:firstName、maxAge
2.大驼峰命名法
适用于类名
如果是一个单词,那么首字母大写。比如:Demo、Test。
如果是多个单词,那么每一个单词首字母都需要大写。比如:HelloWorld
尽量不要用拼音。但是一些国际通用的拼音可视为英文单词。
正确:alibaba、hangzhou、nanjing
错误:jiage、dazhe
平时在给变量名、方法名、类名起名字的时候,不要使用下划线或美元符号。
错误:_name
正确:name
在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,我们之前已经学习过了public
和 private
,接下来我们研究一下protected和默认修饰符的作用。
public:公共的,所有地方都可以访问。
protected:本类 ,本包,其他包中的子类都可以访问。
默认(没有修饰符):本类 ,本包可以访问。
注意:默认是空着不写,不是default
private:私有的,当前类可以访问。
public > protected > 默认 > private
权限范围
private<默认/空着不写
public | protected | 默认 | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中的类 | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:
private
,隐藏细节。 public
,方便创建对象。public
,方便调用方法。补充:
不加权限修饰符,就是默认权限
实际开发中,一般只用private和public
注意:
如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有
在Java中,包(Package)是一种用于组织类和接口的方式,它们通过逻辑上的组织将相关的类和接口归类到一个命名空间中。包的主要目的是避免命名冲突,并提供更好的代码管理和组织结构
包在操作系统中其实就是一个文件夹。包是用来分门别类的管理技术,不同的技术类放在不同的包下,方便管理和维护。
在IDEA项目中,建包的操作如下:
包名的命名规范:
路径名.路径名.xxx.xxx
// 例如:com.itheima.oa
什么时候需要导包?
情况一:在使用Java中提供的**非核心包(java.lang)**中的类时
情况二:使用自己写的其他包中的类时
什么时候不需要导包?
情况一:在使用Java核心包(java.lang)中的类时
情况二:在使用自己写的同一个包中的类时
假设demo1和demo2中都有一个Student该如何使用?
代码示例:
//使用全类名的形式即可。
//全类名:包名 + 类名
//拷贝全类名的快捷键:选中类名crtl + shift + alt + c 或者用鼠标点copy,再点击copy Reference
com.itheima.homework.demo1.Student s1 = new com.itheima.homework.demo1.Student();
com.itheima.homework.demo2.Student s2 = new com.itheima.homework.demo2.Student();
笔记小结:
- 概述:目前用于Java程序开发最好的工具
- 层级结构介绍:project - module - package - class
- 类操作
- 新建类文件
- 删除类文件
- 修改类文件
- 模块操作
- 新建模块
- 删除模块
- 修改模块
- 导入模块
- 项目操作
- 关闭项目
- 打开项目
- 修改项目
- 新建项目
IDEA全称IntelliJ IDEA,是用于Java语言开发的集成环境,它是业界公认的目前用于Java程序开发最好的工具。
补充:
把代码编写,编译,执行,调试等多种功能综合到一起的开发工具
说明:
学习好东西,参考链接:IDEA2023.学习持续更新-搜云库技术团队 (souyunku.com)
步骤一:下载
说明:
下载链接为:https://www.jetbrains.com/idea
步骤二:安装
1.进入安装界面
2.修改安装目录
说明:
建议不要放在C盘
3.额外选项
说明:
勾选64-bit launcher。表示在桌面新建一个64位的快捷方式。
4.安装
5.启动
说明:
选择第二个不导入,保持默认设置,再点击OK
笔记小结
层级关系:project - module - package - class
包含数量:
一个project中可以创建多个module
一个module中可以创建多个package
一个package中可以创建多个class
补充:结构分类
- project(项目、工程)
- module(模块)
- package(包)
- class(类)
淘宝、京东、黑马程序员网站都属于一个个项目,IDEA中就是一个个的Project。
在一个项目中,可以存放多个模块,不同的模块可以存放项目中不同的业务功能代码。在黑马程序员的官方网站中,至少包含了以下模块:
一个模块中又有很多的业务,以黑马程序员官方网站的论坛模块为例,至少包含了以下不同的业务。
为了把这些业务区分的更加清楚,就会用包来管理这些不同的业务。
1.修改字体
说明:
字体选择 Consolas,此字体比较柔和
类的相关操作
模块的相关操作
项目的相关操作
修改项目
点击File,选择Project Structure
在这个界面,默认是Module
所以,要先点击Project
在右侧页面中,输入新的项目名称
修改JDK版本和编译版本都变成JDK14
再点击OK
选择修改之后的项目
点击OK
参考链接:
IntelliJ Idea 常用12款插件(提高开发效率),附优秀主题插件_idea插件_Java技术攀登者的博客-CSDN博客
IDEA值得推荐的20款优秀的插件_idea插件_新猿一马的博客-CSDN博客
笔记小结:
概述:
Java运算符是用于对一个或多个操作数执行操作的特殊符号
表达式是由变量、常量、运算符和方法调用组成的符合语法规则的语句
运算符和表达式区别:
运算符就是对常量或者变量进行操作的符号
表达式就是符合Java语法的式子就是表达式
算术运算符:
定义:算术运算符是用来执行基本的数学运算的
例如:
+、-、 *、 /
自增自减运算符:
定义:自增自减运算符是一种特殊的算数运算符,用于对变量的值进行加1或减1操作
例如:
++、--
赋值运算符:
定义:赋值运算符是Java中用于给变量赋值的运算符
例如:
b = 20;
扩展赋值运算符:
定义:扩展赋值运算符是将算术运算符和赋值运算符组合在一起的运算符
例如:
"+="、 "-="、 "*="、 "/="、 "%="
特点:扩展的赋值运算符中隐层还包含了一个强制转换
关系运算符:
含义:关系运算符是用于比较两个值之间的大小关系
例如:
a > b
注意:区分 == 和 = 赋值运算符和关系运算符
逻辑运算符:
含义:用于多个布尔表达式组合在一起,以生成新的布尔表达式
例如:
true & true、false & false
注意:逻辑运算符还有
!、& 、 |、^
短路逻辑运算符:
含义:如果已经可以确定整个表达式的结果时,就不再继续计算剩下的表达式
例如:
用户名正确 && 密码正确
三元运算符:
含义:被称为条件运算符,它是Java中唯一的具有三个操作数的运算符
格式:
关系表达式 ? 表达式1 :表达式2 ;
例如:
a > b ? a : b
运算符优先级:小括号优先( )
隐式转换与强制转换
隐式转换:自动类型提升
- 取值关系:byte < short < int < long < float < double
- 注意:float类型的存储空间比long类型小,但float类型的表示范围比long类型大
强制转换:强制类型提升
格式:
目标数据类型 变量名 = (目标数据类型)被强转的数据
字符串的+操作(特例):
含义:当+操作中出现了字符,会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后再进行计算
例如:
char c = 'a'; int result = c + 0; System.out.println(result);//9
Java运算符是用于对一个或多个操作数执行操作的特殊符号。表达式是由变量、常量、运算符和方法调用组成的符合语法规则的语句。
定义:就是对常量或者变量进行操作的符号。
比如:
+ - * /
定义:用运算符把常量或者变量连接起来的,符合Java语法的式子就是表达式。
比如:
a + b 这个整体就是表达式。
说明:
而其中+是算术运算符的一种,所以这个表达式也称之为算术表达式。
算术运算符是用来执行基本的数学运算,例如加、减、乘、除和模(取余)运算等。在Java中,算术运算符包括加号(+)、减号(-)、乘号(*)、除号(/)和模运算符(%)等。这些运算符可用于处理数字类型的变量,如int、long、float和double
+ - * / %
+ - * :跟小学数学中一模一样没有任何区别.
/号
/:
1.整数相除结果只能得到整除,如果结果想要是小数,必须要有小数参数。
2.小数直接参与运算,得到的结果有可能是不精确的。
案例:
System.out.println( 10 / 3);//3
System.out.println(10.0 / 3);//3.3333333333333335
%号
%:取模、取余。
他做的也是除法运算,只不过获取的是余数而已。
案例:
System.out.println(10 % 2);//0
System.out.println(10 % 3);//1
应用场景:
//可以利用取模来判断一个数是奇数还是偶数
System.out.println(15 % 2);//1 奇数
演示:键盘录入一个三位数,将其拆分为个位、十位、百位后,打印在控制台
//1.键盘录入一个三位数
//导包 --- 创建对象 --- 接收数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个三位数");
int number = sc.nextInt();//123
//2.获取这个三位数的个位、十位、百位并打印出来
//公式:
//针对于任意的一个数而言
//个位: 数字 % 10
int ones = number % 10;
//十位: 数字 / 10 % 10
int tens = number / 10 % 10;
//百位: 数字 / 100 % 10
int hundreds = number / 100 % 10;
//输出结果
System.out.println(ones);
System.out.println(tens);
System.out.println(hundreds);
细节:
公式:获取任意一个数上每一位数。
个位:数字 % 10
十位:数字 / 10 % 10
百位:数字 / 100 % 10
千位:数字 / 1000 % 10
……
自增自减运算符是一种特殊的算数运算符,用于对变量进行加1或减1的操作。在Java中,自增自减运算符有两种形式:前缀形式和后缀形式。
++ 自增运算符
说明:
++:就是把变量里面的值+1
-- 自减运算符
说明:
--:就是把变量里面的值-1
细节:
不管是先++,还是后++。单独写在一行的时候,运算结果是一模一样的
//++
int a = 10;
a++;//就是让变量a里面的值 + 1
System.out.println(a);//11
++a;//就是让变量a里面的值 + 1
System.out.println(a);//12
赋值运算符是Java中用于给变量赋值的运算符。在Java中,赋值运算符使用等号(=)表示,左边是变量名,右边是赋给变量的值。
public class OperatorDemo6 {
public static void main(String[] args) {
//1.最为简单的赋值运算符用法
int a = 10;//就是把10赋值给变量a
System.out.println(a);
//2.如果等号右边需要进行计算。
int b = 20;
int c = a + b;//先计算等号右边的,把计算的结果赋值给左边的变量
System.out.println(c);
//3.特殊的用法
a = a + 10;//先计算等号右边的,把计算的结果赋值给左边的变量
System.out.println(a);//20
}
}
扩展赋值运算符是指在原有的赋值运算符基础上加上其他算数运算符,例如 +=
, -=
,*=
等等
+=、-=、*=、/=、%=
就是把左边跟右边进行运算,把最终的结果赋值给左边,对右边没有任何影响。
public class OperatorDemo7 {
public static void main(String[] args) {
//扩展赋值运算符
int a = 10;
int b = 20;
a += b;//把左边和右边相加,再把最终的结果赋值给左边,对右边没有任何影响
// 相当于 a = a + b;
System.out.println(a);//30
System.out.println(b);//20
}
}
注意:
扩展的赋值运算符中隐层还包含了一个强制转换
例如:
public class OperatorDemo8 { public static void main(String[] args) { byte a = 10; byte b = 20; //a += b; a = (byte)(a + b); System.out.println(a);//30 } }
说明:以+=为例。a += b ;实际上相当于 a = (byte)(a + b);
又叫比较运算符,其实就是拿着左边跟右边进行了判断而已。
符号 | 解释 |
---|---|
== | 就是判断左边跟右边是否相等,如果成立就是true,如果不成立就是false |
!= | 就是判断左边跟右边是否不相等,如果成立就是true,如果不成立就是false |
> | 就是判断左边是否大于右边,如果成立就是true,如果不成立就是false |
>= | 就是判断左边是否大于等于右边,如果成立就是true,如果不成立就是false |
< | 就是判断左边是否小于右边,如果成立就是true,如果不成立就是false |
<= | 就是判断左边是否小于等于右边,如果成立就是true,如果不成立就是false |
细节:
- 关系运算符最终的结果一定是布尔类型的。要么是true,要么是false
- 在写==的时候,千万不要写成=
逻辑运算符是一种用于连接多个条件表达式的运算符,用于构建复杂的条件表达式
&:逻辑与(而且)
两边都为真,结果才是真,只要有一个为假,那么结果就是假。
|:逻辑或(或者)
两边都为假,结果才是假,只要有一个为真,那么结果就是真。
// & //两边都是真,结果才是真。
System.out.println(true & true);//true
System.out.println(false & false);//false
System.out.println(true & false);//false
System.out.println(false & true);//false
System.out.println("===================================");
// | 或 //两边都是假,结果才是假,如果有一个为真,那么结果就是真。
System.out.println(true | true);//true
System.out.println(false | false);//false
System.out.println(true | false);//true
System.out.println(false | true);//true
根据固定的场景,来选择使用&还是使用|
用户登录。
用户名输入正确 & 密码输入正确
因为只有用户名和密码同时都正确了,那么才能成功登录,只要有一个失败了都不行。
使用技巧:
当我们需要同时满足左边和右边两种情况时,可以使用且
丈母娘选女婿
丈母娘:女婿啊,你要么买个房子,要么买辆车。就可以把我的小棉袄穿走了。
买个房子 | 买辆车
两个条件中,只要满足其中一个,就可以穿走小棉袄了。
使用技巧:
当两种条件只要满足其中一个的时候,可以使用或
在以后用的不多,了解一下即可。
计算规则:如果两边相同,结果为false,如果两边不同,结果为true
代码示例:
//^ //左右不相同,结果才是true,左右相同结果就是false
System.out.println(true ^ true);//false
System.out.println(false ^ false);//false
System.out.println(true ^ false);//true
System.out.println(false ^ true);//true
是取反,也叫做非。
计算规则:false取反就是true,true取反就是false
温馨提示:取反最多只用一个。
代码示例:
System.out.println(!false);//true
System.out.println(!true);//false
System.out.println(!!false);//报错
细节:
注意点:取反最多只用一个
短路逻辑运算符是指在逻辑运算中,如果能够根据左侧的表达式的值得出整个逻辑表达式的结果,就不再对右侧的表达式进行计算
&&
运算结果跟&是一模一样的,只不过具有短路效果。
||
运算结果跟|是一模一样的。只不过具有短路效果。
逻辑核心:
当左边不能确定整个表达式的结果,右边才会执行。
当左边能确定整个表达式的结果,那么右边就不会执行了。从而提高了代码的运行效率。
1.用户登录案例
用户名正确 & 密码正确
如果使用一个&,不管用户名是否正确都会去验证密码。
思考:
如果用户名输入正确了,那么我们再判断密码是否正确,是符合业务逻辑的。
但是如果用户名输入错误了,那么现在还有必要去比较密码吗?没有不要了。
如果使用一个&,那么左边和右边不管什么情况下,都会执行。
用户名正确 && 密码正确
如果用户名输入正确了,那么才会验证密码是否输入正确。
如果用户名输入错误了,那么就不会再去验证密码是否正确,最终的结果直接为false。从而提高了程序运行的效率。
2.丈母娘选女婿
有房 | 有车
首先先看看有没有房,发现有,然后再去看看有没有车。
思考:
既然都有房子,干嘛还要去看车呢?多此一举。
有房 || 有车
首先先看看有没有房,如果有,那么右边就不执行了。最终的结果直接为true。
如果没有房子,才会去看右边有没有车。
&& 和 & 、||和|的运行结果都是一模一样的。
但是短路逻辑运算符可以提高程序的运行效率。
最为常用: && || !
三元表达式或者问号冒号表达式。
关系表达式 ? 表达式1 :表达式2 ;
细节:
- 计算关系表达式的值。
- 如果关系表达式的值为真,那么执行表达式1。
- 如果关系表达式的值为假,那么执行表达式2。
注意:
三元运算符的最终结果一定要被使用,要么赋值给一个变量,要么直接打印出来。
public class OperatorDemo12 {
public static void main(String[] args) {
//需求:求两个数的较大值
int a = 10;
int b = 20;
//格式:关系表达式 ? 表达式1 : 表达式2 ;
//注意点:
//三元运算符的最终结果一定要被使用。
//要么赋值给一个变量,要么直接输出。
int max = a > b ? a : b ;
System.out.println(max);
System.out.println(a > b ? a : b);
}
}
在Java中涉及了很多的运算符,每一种运算符都有各自的优先级。但是这些优先级不需要记忆。咱们只要知道其中一点:小括号优先于所有
在Java中,隐式转换就是把一个取值范围小的数据或者变量,赋值给另一个取值范围大的变量。此时不需要我们额外写代码单独实现,是程序自动帮我们完成的。也叫自动类型提升。换句话说,就是小的范围数据类型可以给大的范围数据类型,可以直接给
byte < short < int < long < float < double
如果要把一个取值范围大的数据或者变量赋值给另一个取值范围小的变量。是不允许直接操作。
目标数据类型 变量名 = (目标数据类型)被强转的数据;
public class OperatorDemo2 {
public static void main(String[] args) {
double a = 12.3;
int b = (int) a;
System.out.println(b);//12
}
}
注意点:
强制转换有可能会导致数据发生错误。(数据的精度丢失)
当+操作中出现了字符,会拿着字符到计算机内置的ASCII码表中去查对应的数字,然后再进行计算。
char c = 'a';
int result = c + 0;
System.out.println(result);//97
说明:
ASCII码表中:
‘a’ ----- 97
‘A’ ----- 65
在Java中,位移运算符是一种操作二进制位的运算符,它可以对整数类型的数据进行位移操作。Java提供了三种位移运算符:左移(<<),右移(>>),无符号右移(>>>)
这些位移运算符在处理整数的二进制位时非常有用,常用于位操作、位标志的设置和清除,以及优化特定的算法。请注意,位移运算符仅适用于整数类型(如int、long等),不适用于浮点数类型。
笔记小结:
流程控制语句
顺序结构:
- 含义:按照编写顺序依次执行的结构
判断和选择结构
含义:根据条件的不同而选择执行不同代码块的结构
例如:
if、switch
循环结构
含义:重复执行某段代码的结构
例如:
while、do…while、for
循环间的区别:1.for和while循环,是先判断,再执行。2.do…while是先执行,再判断
条件控制语句
含义:是一种程序控制结构,用于基于某些条件来执行或跳过代码块
例如:
break、continue
注意:条件控制语句在非循环结构中,不能使用
Java控制语句是用于控制程序流程执行的语句,它们可以根据条件或循环来改变程序的执行顺序。控制语句可以帮助你实现不同的条件逻辑和循环结构,从而实现不同的任务和功能。
Java控制语句分为:流程控制语句、条件控制语句
在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。所以,我们必须清楚每条语句的执行流程。而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能
顺序结构
判断和选择结构(if, switch)
循环结构(for, while, do…while)
顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的
格式:
if (关系表达式) {
语句体;
}
执行流程:
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体
③如果关系表达式的值为false就不执行语句体
④继续执行后面的语句内容
示例:
public class IfDemo {
public static void main(String[] args) {
System.out.println("开始");
//定义两个变量
int a = 10;
int b = 20;
//需求:判断a和b的值是否相等,如果相等,就在控制台输出:a等于b
if(a == b) {
System.out.println("a等于b");
}
//需求:判断a和c的值是否相等,如果相等,就在控制台输出:a等于c
int c = 10;
if(a == c) {
System.out.println("a等于c");
}
System.out.println("结束");
}
}
格式:
if (关系表达式) {
语句体1;
} else {
语句体2;
}
执行流程:
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体1
③如果关系表达式的值为false就执行语句体2
④继续执行后面的语句内容
示例:
public class IfDemo02 {
public static void main(String[] args) {
System.out.println("开始");
//定义两个变量
int a = 10;
int b = 20;
//需求:判断a是否大于b,如果是,在控制台输出:a的值大于b,否则,在控制台输出:a的值不大于b
if(a > b) {
System.out.println("a的值大于b");
} else {
System.out.println("a的值不大于b");
}
System.out.println("结束");
}
}
if语句格式3
格式:
if (关系表达式1) {
语句体1;
} else if (关系表达式2) {
语句体2;
}
…
else {
语句体n+1;
}
执行流程:
①首先计算关系表达式1的值
②如果值为true就执行语句体1;如果值为false就计算关系表达式2的值
③如果值为true就执行语句体2;如果值为false就计算关系表达式3的值
④…
⑤如果没有任何关系表达式为true,就执行语句体n+1。
格式
switch (表达式) {
case 1:
语句体1;
break;
case 2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
执行流程:
首先计算出表达式的值
其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结 束。
最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。
default的位置和省略情况
default可以放在任意位置,也可以省略
case穿透
不写break会引发case穿透现象
switch在JDK12的新特性
int number = 10;
switch (number) {
case 1 -> System.out.println("一");
case 2 -> System.out.println("二");
case 3 -> System.out.println("三");
default -> System.out.println("其他");
}
当我们需要对一个范围进行判断的时候,用if的第三种格式
当我们把有限个数据列举出来,选择其中一个执行的时候,用switch语句
比如:
小明的考试成绩,如果用switch,那么需要写100个case,太麻烦了,所以用if简单。
如果是星期,月份,客服电话中0~9的功能选择就可以用switch
循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复 执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形 成死循环。
for循环格式:
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
格式解释:
执行流程:
①执行初始化语句
②执行条件判断语句,看其结果是true还是false
如果是false,循环结束
如果是true,继续执行
③执行循环体语句
④执行条件控制语句
⑤回到②继续
for循环书写技巧:
代码示例:
//1.确定循环的开始条件
//2.确定循环的结束条件
//3.确定要重复执行的代码
//需求:打印5次HelloWorld
//开始条件:1
//结束条件:5
//重复代码:打印语句
for (int i = 1; i <= 5; i++) {
System.out.println("HelloWorld");
}
格式:
初始化语句;
while(条件判断语句){
循环体;
条件控制语句;
}
本知识点了解即可
格式:
初始化语句;
do{
循环体;
条件控制语句;
}while(条件判断语句);
特点:
先执行,再判断。
for和while循环,是先判断,再执行。
do…while是先执行,再判断。
当知道循环次数或者循环范围的时候,用for循环。
当不知道循环次数,也不知道循环范围,但是知道循环的结束条件时,用while循环。
概念:
又叫死循环。循环一直停不下来。
for格式:
for(;;){
System.out.println("循环执行一直在打印内容");
}
解释:
初始化语句可以空着不写,表示循环之前不定义任何的控制变量。
条件判断语句可以空着不写,如果不写,默认表示true,循环一直进行。
条件控制语句可以空着不写,表示每次循环体执行完毕后,控制变量不做任何变化。
while格式:
while(true){
System.out.println("循环执行一直在打印内容");
}
解释:
小括号里面就不能省略了,true一定要写出来,否则代码会报错。
do…while格式:
do{
System.out.println("循环执行一直在打印内容");
}while(true);
解释:
小括号里面就不能省略了,true一定要写出来,否则代码会报错。
无限循环的注意事项:
不能单独存在的。可以用在switch和循环中,表示结束,跳出的意思。
代码示例:
//1.吃1~5号包子
for (int i = 1; i <= 5; i++) {
System.out.println("在吃第" + i + "个包子");
//2.吃完第三个的时候就不吃了
if(i == 3){
break;//结束整个循环。
}
}
不能单独存在的。只能存在于循环当中。
表示:跳过本次循环,继续执行下次循环。
代码示例:
//1.吃1~5号包子
for (int i = 1; i <= 5; i++) {
//2.第3个包子有虫子就跳过,继续吃下面的包子
if(i == 3){
//跳过本次循环(本次循环中,下面的代码就不执行了),继续执行下次循环。
continue;
}
System.out.println("在吃第" + i + "个包子");
}
Random跟Scanner一样,也是Java提前写好的类,我们不需要关心是如何实现的,只要直接使用就可以了。
笔记小结:
定义:数组指的是一种容器,可以同来存储同种数据类型的多个值
定义方式:
格式一:
数据类型 [] 数组名; //例如 int [] array;
格式二:
数据类型 数组名 []; //例如 int array [];
注意:不同的数据类型对应不同的默认值
- 整数类型:0
- 小数类型:0.0
- 布尔类型:false
- 字符类型:‘\u0000’
- 引用类型:null
静态数组初始化:
格式一:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...}; //例如 double[] arr = new double[]{1.1,1.2,1.3};
格式二:
数据类型[] 数组名 = {元素1,元素2,元素3,元素4...}; //例如 int[] array = {1,2,3,4,5};
动态数组初始化:
格式:
数据类型[] 数组名 = new 数据类型[数组的长度]; //例如 double[] arr = new double[10];
数组动态初始化与数组的静态初始化的区别:
- 语法不同
- 数组长度不同
- 赋值时机不同
- 注意:无论是何种数组,数组的最大长度为,数组的长度-1。例如:arr.length - 1
地址值:
含义:数组的地址值是指向数组对象的指针或引用
例如:
int[] arr = {1,2,3,4,5}; System.out.println(arr); //[I@6d03e736 /* [ :表示现在打印的是一个数组。 I:表示现在打印的数组是int类型的。 @:仅仅是一个间隔符号而已。 6d03e736:就是数组在内存中真正的地址值。(十六进制的) */
索引:
含义:用来标识它在数组中的位置
例如:
arr[0]、arr[1]、……
特点:
- 起始值为 0
- 连续不间断
- 逐个+1增长。
数组元素访问
- 含义:根据索引访问数组中的值
- 格式:数组名[索引];
遍历
含义:依次取出元组中的元素
格式:
for(int i = 0; i < arr.length; i++){ //在循环的过程中,i依次表示数组中的每一个索引 sout(arr[i]);//就可以把数组里面的每一个元素都获取出来,并打印在控制台上了。 }
说明:arr.length 表示获取数组的长度
在Java中,数组指的是一种容器,可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候,需要结合隐式转换考虑
注意:数组中的隐式转换
- 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的,但是byte类型,short类型,int类型的数据是可以存到这个数组里面的
容器的类,和存储的数据类型保持一致
说明:
- 整数1 2 3 4 56 就可以使用int类型的数组来存储。
- 小数1.1 1.2 1.3 1.4 就可以使用double类型的数组来存储。
- 字符串"aaa" “bbb” “ccc” 就可以使用String类型的数组来存储。
数据类型 [] 数组名
# 例如
int [] array
数据类型 数组名 []
# 例如
int array []
细节:
- 数据类型:限定了数组以后能存什么类型的数据。
- 数组的默认初始化值:
- 整数类型:0
- 小数类型:0.0
- 布尔类型:false
- 字符类型:‘\u0000’
- 引用类型:null
- 方括号:表示现在定义的是一个数组。
- 数组名:就是一个名字而已,方便以后使用。
注意:
方法括号跟数组名,谁写在前面,谁写在后面都是一样的
/* 完整格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3,元素4...}; */
int[] arr = new int[]{11,22,33};
double[] arr = new double[]{1.1,1.2,1.3};
/* 简化格式:
数据类型[] 数组名 = {元素1,元素2,元素3,元素4...}; */
int[] array = {1,2,3,4,5};
double[] array = {1.1,1.2,1.3};
细节:
- 数据类型:限定了数组以后能存什么类型的数据
- 方括号:表示现在定义的是一个数组
- 数组名:其实就是名字而已,方便以后使用,在起名字的时候遵循小驼峰命名法
- new:就是给数组在内存中开辟了一个空间
- 大括号:表示数组里面的元素。元素也就是存入到数组中的数据。多个元素之间,一定要用逗号隔开
注意:
- 前面和后面的数据类型一定要保持一致
- 数组一旦创建之后,长度不能发生变化
/* 格式:
数据类型[] 数组名 = new 数据类型[数组的长度]; */
int[] agesArr = new int[3];
int[] scoresArr = new int[10];
int[] arr = {1,2,3,4,5};
System.out.println(arr);//[I@6d03e736
double[] arr2 = {1.1,2.2,3.3};
System.out.println(arr2);//[D@568db2f2
细节:
打印数组的时候,实际出现的是数组的地址值。数组的地址值:就表示数组在内存中的位置。
地址详细介绍
/* 以[I@6d03e736为例: [ :表示现在打印的是一个数组。 I:表示现在打印的数组是int类型的。 @:仅仅是一个间隔符号而已。 6d03e736:就是数组在内存中真正的地址值。(十六进制的) 但是,我们习惯性会把[I@6d03e736这个整体称之为数组的地址值 */
在Java中,索引也叫角标、下标。换句话说,就是数组容器中每一个小格子对应的编号。
获取数组中对应索引上的值
修改数组中对应索引上的值,一旦修改之后,原来的值就会被覆盖
public class ArrDemo2 {
/*
数组中元素访问的格式:
数组名[索引];
作用:
1.获取指定索引上对应的元素
2.修改指定索引上对应的元素
*/
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
//需求1:获取arr数组中,3索引上的值
int number = arr[3];
System.out.println(number);
System.out.println(arr[3]);
//需求2:将arr数组中,3索引上的值修改为10
arr[3] = 10;
System.out.println("修改之后为:" + arr[3]);
}
}
就是把数组里面所有的内容一个一个全部取出来。
/* 格式:
数组名.length */
for(int i = 0; i < arr.length; i++){
//在循环的过程中,i依次表示数组中的每一个索引
sout(arr[i]);//就可以把数组里面的每一个元素都获取出来,并打印在控制台上了。
}
int[] arr = {1,2,3,4,5};
说明:
手动指定数组的元素,系统会根据元素的个数,计算出数组的长度。
int[] arr = new int[3];
说明:
手动指定数组长度,由系统给出默认初始化值。
说明:
// 使用数组来存储键盘录入的5个整数。 int[] arr = new int[5];
说明:
// 将全班的学生成绩存入数组中,已知学生成绩为:66,77,88,99,100 int[] arr = {66,77,88,99,100}
索引越界
public class ArrDemo6 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,5,5,5,5};
//用索引来访问数组中的元素
System.out.println(arr[1]);
System.out.println(arr[10]);//ArrayIndexOutOfBoundsException
}
}
说明:针对于任意一个数组,索引的范围
- 最小索引:0
- 最大索引:
- 数组的长度 - 1
- 数组名.length - 1
笔记小结:
局部代码块:略
构造代码块:略
静态代码块(重点)
含义:被static修饰的代码块
基本用例:
/*格式: static{},需要通过static关键字修饰 */ static{ } // 当类加载时,此代码块就会被加载
特点:随着类的加载而加载,并且自动出发,只执行一次
public class CodeBlockLearn {
public static void main(String[] args) {
{
int a=10;
System.out.println(a);
}
}
}
说明:
- 应用场景:那么当超出了方括号,变量a也就不存在了,有着提前释放变量的作用
说明:
构造代码块优先于构造方法而执行的
/*格式:
static{},需要通过static关键字修饰 */
public class MyClass {
static {
System.out.println("静态代码块执行了");
}
public static void main(String[] args) {
System.out.println("主方法执行了");
}
}
说明:
- 执行时机:随着类的加载而加载,并且自动出发,只执行一次
- 使用场景:在类加载时,做一些初始化的操作
笔记小结:见各模块
笔记小结:
定义:当我们在一个类中使用
this
时,它指的是该类的当前对象。基础用例:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; //使用this关键字引用当前对象的成员变量name this.age = age; //使用this关键字引用当前对象的成员变量age } }
定义:在 Java 中,this 是一个关键字,表示当前对象。它可以用于访问当前对象的属性和方法。
基本用例
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name; //使用this关键字引用当前对象的成员变量name
this.age = age; //使用this关键字引用当前对象的成员变量age
}
}
说明:
当我们在一个类中使用
this
时,它指的是该类的当前对象。
笔记小结:
定义:static是一个关键字,用于修饰类的成员变量、成员方法和代码块,其作用是将这些成员变量、成员方法和代码块与类本身关联,而不是与类的实例对象关联
静态变量及其访问
含义:static修饰类的成员变量
定义:
/* 格式: 修饰符 static 数据类型 变量名 = 初始值;*/ public static String schoolName = "传智播客";
访问:
/* 格式: 类名.静态变量 */ System.out.println(Student.schoolName); // 传智播客
实例变量及其访问
含义:无static修饰类的成员变量
定义:
/* 格式: 修饰符 数据类型 变量名 = 初始值; */ public String schoolName = "传智播客";
访问:
/* 格式: 对象.方法名 */ Student stu = new Student(); System.out.println(stu.schoolName);
注意:
- 实例变量是属于每个对象,必须创建类的对象才可以访问
- 静态变量不属于成员对象,属于类。该静态变量的加载随着类的加载而加载,优先于对象存在
静态方法及其访问
含义:static修饰类的成员方法
定义:
/* 格式: 修饰符 static 类型 方法名() */ public static void study(){ // 类方法或者静态方法。 System.out.println("我们都在黑马程序员学习"); }
访问:通过类名.方法名()
/* 格式: 类名.方法名() */ Student.study();
注意:实例方法是属于每个对象,必须创建类的对象才可以访问
实例方法及其访问
含义:无static修饰类的成员方法
定义:
/* 格式: 修饰符 类型 方法名()*/ public void study(){ // 类方法或者静态方法。 System.out.println("我们都在黑马程序员学习"); }
访问:需要new对象
/* 格式: 对象.方法名 */ Student stu = new Student(); System.out.println(stu.study());
内存图:
- 当使用了static关键字,会在堆内存中开辟一个名叫“静态存储位置”的内存空间
- 静态方法不能访问非静态资源
- 静态方法不能调用实例变量
- 非静态资源可以访问所有
- 注意,静态成员的生命周期与类的生命周期一样长
static是一个关键字,用于修饰类的成员变量、成员方法和代码块,其作用是将这些成员变量、成员方法和代码块与类本身关联,而不是与类的实例对象关联
有static修饰成员变量,说明这个成员变量是属于类的,这个成员变量称为类变量或者静态成员变量。 直接用 类名访问即可。因为类只有一个,所以静态成员变量在内存区域中也只存在一份。所有的对象都可以共享这个变量。
/* 格式:
修饰符 static 数据类型 变量名 = 初始值;*/
public class Student {
public static String schoolName = "传智播客"; // 类变量或者静态成员变量
// .....
}
/*格式:
类名.静态变量 */
public static void main(String[] args){
System.out.println(Student.schoolName); // 传智播客
Student.schoolName = "黑马程序员";
System.out.println(Student.schoolName); // 黑马程序员
}
无static修饰的成员变量属于每个对象的, 这个成员变量叫实例变量,之前我们写成员变量就是实例成员变量。
public class Student {
public String schoolName = "传智播客"; // 成员变量
// .....
}
/* 格式:
对象.实例成员变量 */
public static void main(String[] args) {
Student stu = new Student();
System.out.println(stu.schoolName);
}
细节:
实例成员变量属于每个对象,必须创建类的对象才可以访问。
有static修饰成员方法,说明这个成员方法是属于类的,这个成员方法称为类方法或者静态方法。 直接用 类名访问即可。因为类只有一个,所以静态方法在内存区域中也只存在一份。所有的对象都可以共享这个方法。
与静态成员变量一样,静态方法也是直接通过类名.方法名称即可访问。
public class Student{
public static String schoolName = "传智播客";
// .....
public static void study(){ // 类方法或者静态方法。
System.out.println("我们都在黑马程序员学习");
}
}
/* 格式:
类名.静态方法*/
public static void main(String[] args){
Student.study();
}
无static修饰的成员方法属于每个对象的,这个成员方法也叫做实例方法。
细节
实例方法是属于每个对象,必须创建类的对象才可以访问
/*格式:
对象.实例方法*/
public class Student {
// 实例变量
private String name ;
// 2.方法:行为
// 无 static修饰,实例方法。属于每个对象,必须创建对象调用
public void run(){
System.out.println("学生可以跑步");
}
// 无 static修饰,实例方法
public void sleep(){
System.out.println("学生睡觉");
}
public static void study(){
}
}
public static void main(String[] args){
// 创建对象
Student stu = new Student ;
stu.name = "徐干";
// Student.sleep();// 报错,必须用对象访问。
stu.sleep();
stu.run();
}
小结
1.当 static
修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。
2.无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。
3.static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。
4.无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用。
静态方法
说明:
若想让类中的某个成员变量被共享,可以将它变为static给修饰,这就是static的内存中的执行流程
补充:
方法入栈后会退出
注意事项:静态方法不能访问非静态
说明:
- 若name是非static修饰,则不会出现在堆内存中的静态存储位置,因此静态方法不能访问非静态
- 现在堆内存中并没有任何实例过的对象,因此静态方法不能调用实例变量
补充:
main方法中读取到Student.teacherName方法的Student时,会把Student.class字节码文件加载到方法区
说明:
假如method方法中可以调用show方法,那么在栈内存中,这个???.show方法又是谁来进行调用,正常来说应该是由一个对象来进行调用,因此静态方法不能访问非静态
补充:
静态成员的生命周期与类的生命周期一样长,也就是说,当类被加载时,静态成员就被分配内存;当类被卸载时,静态成员所占用的内存也被释放。
帮助我们做一些事情的,但是不描述任何事物的类
1.有同学没听懂,我这里解释一下,上节课说到静态变量先于类创建
2.意思就是我先加载静态变量,再创建类,是按照这个步骤来的
3.那么 ,如果这个类只有方法,也就是工具类,我没必要创建这个类
4.因为我可以先于这个类直接调用方法,而只有静态方法可以优先被创建
static静态方法执行–内存分析_静态方法运行时存在的_qingdao_java的博客-CSDN博客
笔记小结:
定义:
final
是一个关键字,它可以用来修饰变量、方法和类,表示不可改变的、终态的。修饰变量:
局部变量:表示它的值不能被改变,即该变量为常量。变量值不可被修改
final int a; a = 10;
成员变量:表示它的值不能被改变,即该变量为常量。变量只可在定义成员变量的时候立马赋值
final int num = 10;
变量明明规范:单个单词全部大写,多个单词间使用下划线隔开
修饰方法:表示该方法不能被子类重写(覆盖)
final public void show1() { System.out.println("Fu2 show1"); }
修饰类:表示该类被称为称为最终类(或不可扩展类),因为不能被其余类继承
final class Fu { }
细节:
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,是其指向的对象的内容可以被修改
final
是一个关键字,它可以用来修饰变量、方法和类,表示不可改变的、终态的。
final
修饰的变量表示常量,一旦被赋值后,就不能再被改变。final
声明的变量必须在声明时或者在构造器中初始化,否则编译器会报错。final
变量时,一般使用全大写字母和下划线来表示。final
修饰的方法表示该方法不能被子类重写或覆盖。final
时,其中所有的方法都会自动地成为 final
,但是实例变量不会受到影响。final
修饰的类表示该类不能被继承。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修饰的常量名称,一般都有书写规范,所有字母都大写。
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修饰的类,不能被继承
/* 格式:
final class 类名 {
} */
final class Fu {
}
// class Zi extends Fu {} // 报错,不能继承final的类
说明:
查询API发现像
public final class String
、public final class Math
、public final class Scanner
等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。
笔记小结:
- 概述:用于修饰类的成员变量和方法的修饰符
- 作用:防止外部程序对对象的数据进行非法访问和操作
private是一个修饰符,可以用来修饰成员(成员变量,成员方法)
说明:
被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
细节:
- 提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
- 提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
/*
学生类
*/
class Student {
//成员变量
String name;
private int age;
//提供get/set方法
public void setAge(int a) {
if(a<0 || a>120) {
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();
}
}
需求:定义标准的学生类,要求name和age使用private修饰,并提供set和get方法以及便于显示数据的show方法,测试类中创建对象并使用,最终控制台输出 林青霞,30
示例代码:
/*
学生类
*/
class Student {
//成员变量
private String name;
private int age;
//get/set方法
public void setName(String n) {
name = n;
}
public String getName() {
return name;
}
public void setAge(int a) {
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();
//使用set方法给成员变量赋值
s.setName("林青霞");
s.setAge(30);
s.show();
//使用get方法获取成员变量的值
System.out.println(s.getName() + "---" + s.getAge());
System.out.println(s.getName() + "," + s.getAge());
}
}
笔记小结:
- 含义:this的本质就是所在方法调用者的地址值
- 内存图:
- 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量
- 方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量
this关键字内存原理(重点)
说明:
方法执行完成后会出栈
总结一句话:this的本质就是所在方法调用者的地址值
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);
}
}
笔记小结:
含义:表示父类对象的引用,可以用来调用父类的构造方法、实例方法和实例变量
用法格式:
this.成员变量 -- 本类的 super.成员变量 -- 父类的 this.成员方法名() -- 本类的 super.成员方法名() -- 父类的 super(...) -- 调用父类的构造方法,根据参数匹配确认 this(...) -- 调用本类的其他构造方法,根据参数匹配确认
super用法示例:
- super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现
- super(…)是根据参数去确定调用父类哪个构造方法的
内存图:
细节:
子类的每个构造方法中均有默认的super( ),调用父类的空参构造。手动调用父类构造会覆盖默认的super( )
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现
super( )和this( )是根据参数去确定调用父类哪个构造方法的
super( )可以调用父类构造方法初始化继承自父类的成员变量的数据
this( )可以调用本类中的其他构造方法
在Java中super关键字,表示父类对象的引用,可以用来调用父类的构造方法、实例方法和实例变量
class Person {
private String name;
private int age;
public Person() {
System.out.println("父类无参");
}
// getter/setter省略
}
class Student extends Person {
private double score;
public Student() {
//super(); // 调用父类无参构造方法,默认就存在,可以不写,必须再第一行
System.out.println("子类无参");
}
public Student(double score) {
//super(); // 调用父类无参构造方法,默认就存在,可以不写,必须再第一行
this.score = score;
System.out.println("子类有参");
}
// getter/setter省略
}
public class Demo07 {
public static void main(String[] args) {
// 调用子类有参数构造方法
Student s2 = new Student(99.9);
System.out.println(s2.getScore()); // 99.9
System.out.println(s2.getName()); // 输出 null
System.out.println(s2.getAge()); // 输出 0
}
}
说明:
我们发现,子类有参数构造方法只是初始化了自己对象中的成员变量score,而父类中的成员变量name和age依然是没有数据的,怎么解决这个问题呢,我们可以借助与super(…)去调用父类构造方法,以便初始化继承自父类对象的name和age
/* 格式:
super.成员变量 -- 父类的
super.成员方法名() -- 父类的 */
class Person {
private String name ="凤姐";
private int age = 20;
public Person() {
System.out.println("父类无参");
}
public Person(String name , int age){
this.name = name ;
this.age = age ;
}
// getter/setter省略
}
class Student extends Person {
private double score = 100;
public Student() {
//super(); // 调用父类无参构造方法,默认就存在,可以不写,必须再第一行
System.out.println("子类无参");
}
public Student(String name , int age,double score) {
super(name ,age);// 调用父类有参构造方法Person(String name , int age)初始化name和age
this.score = score;
System.out.println("子类有参");
}
// getter/setter省略
}
public class Demo07 {
public static void main(String[] args) {
// 调用子类有参数构造方法
Student s2 = new Student("张三",20,99);
System.out.println(s2.getScore()); // 99
System.out.println(s2.getName()); // 输出 张三
System.out.println(s2.getAge()); // 输出 20
}
}
注意:
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
super(…)是根据参数去确定调用父类哪个构造方法的。
父类空间优先于子类对象产生
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造器调用时,一定先调用父类的构造方法。理解图解如下:
this(…)
/* 格式:
this.成员变量 -- 本类的
this.成员方法名() -- 本类的 */
package com.itheima._08this和super调用构造方法;
/**
* this(...):
* 默认是去找本类中的其他构造方法,根据参数来确定具体调用哪一个构造方法。
* 为了借用其他构造方法的功能。
*/
public class ThisDemo01 {
public static void main(String[] args) {
Student xuGan = new Student();
System.out.println(xuGan.getName()); // 输出:徐干
System.out.println(xuGan.getAge());// 输出:21
System.out.println(xuGan.getSex());// 输出: 男
}
}
class Student{
private String name ;
private int age ;
private char sex ;
public Student() {
// 很弱,我的兄弟很牛逼啊,我可以调用其他构造方法:Student(String name, int age, char sex)
this("徐干",21,'男');
}
public Student(String name, int age, char sex) {
this.name = name ;
this.age = age ;
this.sex = sex ;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
说明:
this内存图,已在this关键字详细讲解
在Java中,执行一个HelloWorld
方法的内存图
说明:
栈内存为方法提供使用、堆内存为对象提供使用、方法区为执行的class文件临时存储
补充:
- 参考资料:https://www.bilibili.com/video/BV17F411T7Ao/?p=107
- 当执行main方法时,会生成StringDemo这个class文件
说明:
Ctrl+Alt+B
选中一个方法,按键Ctrl+Alt+B即可查看实现此接口的实现类
Ctrl+F12可以查看当前类中的状态,例如成员方法,成员属性等等
C表示类,M表示方法,F表示常量或静态成员变量,➡️表示继承,⬆表示重写
在Java中,int
是一种原始数据类型(primitive data type),用于表示整数值。它是Java中最常用的数据类型之一,它的大小为4个字节(32位),可以表示介于-2,147,483,648和2,147,483,647之间的整数。
而Integer
是Java中的一个类(Class),它封装了一个基本类型的int的值。它允许将int值作为参数传递给需要一个对象的方法,也可以将int值转换为其他类型的值,例如字符串。
因此,int
和Integer
的主要区别在于int
是一个原始数据类型,而Integer
是一个类,用于封装int值以便进行更多的操作。此外,int
在Java中是一种基本数据类型,而Integer
是一种引用数据类型,也就是说Integer
实际上是一个指向对象的指针,而不是一个简单的数据值。
String
是一种对象,用于表示一个字符序列(即一组字符)。它是Java中的一个类,具有许多实用方法来操作和处理字符串,例如连接、替换、搜索和分割等。字符串常量可以使用双引号括起来,例如"hello"
。
Character
是Java中的char类型的包装类,它用于表示单个字符。每个Character
对象都包含一个char类型的值。它也具有一些实用方法来操作和处理字符,例如将字符转换为大写或小写。字符常量可以使用单引号括起来,例如'A'
。
因此,String
和Character
的主要区别在于它们表示的数据类型不同。String
用于表示一组字符,而Character
用于表示单个字符。此外,String
是一个类,而Character
是一个简单的数据类型。在Java中,字符串是不可变的,因此不能在原始字符串上进行修改,而Character
是可变的,因为它只表示一个字符。
参考链接:(29条消息) 基本数据类型和引用数据类型的区别_Brandon懂你的博客-CSDN博客