#top 写在最前面
水滴石穿,稳固基础,基础永远是最需要注重的
文章仅作为JAVA编程复习使用
文章参考博主:<狂神说>、<生命是有光的>
JAVA编程核心基础(二)—面向对象
JAVA编程核心基础(三)—抽象与接口
Java编程核心基础(四)—异常
Java编程核心基础(五)—线程
Java入门了解
Java语言有哪些特点?
- 简单易学;
- 面向对象(封装,继承,多态);
- 平台无关性( Java 虚拟机实现平台无关性);
- 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持);
- 可靠性;
- 安全性;
- 支持网络编程并且很方便( Java 语言诞生本身就是为简化网络编程设计的,因此 Java 语言不仅支持网络编程而且很方便);
- 编译与解释并存;
Java 程序从源代码到运行一般有下面 3 步:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PUrYffh0-1627393423704)(D:\计算机语言\图片\JAVA编译过程.png)]
JVM vs JDK vs JRE
JVM:
Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
什么是字节码?采用字节码的好处是什么?
在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。
JDK 是 Java Development Kit 缩写,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。
JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。
1、基础语法篇
1-1、注释
/
注释 分为
单行注释: //
多行注释: /加/
文档注释: / 加/ 就是现在在注释的
/
1-2、标识符
关键字 :一下仅举例,详细可百度JAVA关键字
abstract(表明类或者成员方法具有抽象属性)、assert(断言,用来进行程序调试)、boolean(基本数据类型之一,声明布尔类型的关键字)、
break(提前跳出一个块)、byte(基本数据类型之一,字节类型)、case(用在switch语句之中,表示其中的一个分支)、
catch(用在异常处理中,用来捕捉异常)、char(基本数据类型之一,字符类型)、class(声明一个类)....
- Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
- 所有的标识符都应该以字母,美元符($)、或者下划线开始
- 首字母之后可以是字母,美元符,下划线或数字的任何字符组合
- 不能使用关键字作为变量名或方法名
- 标识符是大小写敏感的
- 合法标识符举例:age、$salary,_value、__1_value
- 非法标识符距离:123abc、-salary、#abc
1-3、修饰符
- public 公用的
- protected 受保护的
- private 一般会设置属性为私有的 在这个声明里定义的属性,需要通过get和set去进行获取/设置
- final 被final定义的类 无法被继承;断子绝孙= = 被final定义的属性 为常量
- static 静态 集中在定义 静态方法, 也有静态代码块 例如 static{} 详情见下面的Fifth类代码
private | default | protected | public | |
---|---|---|---|---|
本类中 | √ | √ | √ | √ |
本包下的其他类中 | × | √ | √ | √ |
其他包下的类中 | × | × | × | √ |
其他包下的子类中 | × | × | √ | √ |
1-4、数据类型
数据类型分为:基本数据类型、引用数据类型
基本数据类型:
整数: 浮点数: 字符:——>联想到ASCII码, UTF-8 , Unicode码
byte 占1个字节 float 占4个字节 char 占2个字节
short 占2个字节 double 占8个字节 转义字符:\u0000, \n ,\r ,\t ,\
int 占4个字节
布尔值:
long 占8个字节 boolean 占1个字节
0b开头为二进制 、0 八进制 、0x十六进制
引用数据类型:
类:栈指向堆
接口:
数组:
1-5、类型转换
强制类型转换: 高转低 (低)高
int a = 10; // int 4个字节
byte b = (byte)a; // byte 1个字节
double num1 = 12.9;
int num2 = (int)num1;
System.out.println(num1); // 12
通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可以实现把字符串转换成基本类型
自动类型转换: 低转高 子类转父类
public class Demo {
public static void main(String[] args){
int a = 10; // int 4个字节
double b = a; // double 8个字节
System.out.println(b) // 10.0
}
}
注意点:
- 不能对布尔值进行转换
- 不能把对象类型转换为不相关的类型
- 在把高容量转换到低容量的时候,强制转换
- 转换的时候可能存在内存溢出,或者精度问题!
1-6、变量与常量
变量
- 变量是什么:就是可以变化的量!
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
变量作用域
- 类变量:从属于类的,一起出现,一起消失,加了static,能直接输出
- 实例变量 从属于对象的
- 局部变量
常量
-
常量(Constant):初始化(initialize)后不能再改变值!不会变动值。
-
所谓常量可以理解成一种特殊的变量,他的值被设定后,在程序运行过程中不允许被改变。
-
常量名一般使用大写字符。
final 常量名 = 值; 如 : final double PI = 3.14;
命名规范:
1.见名知意 2.驼峰命名:首字母小写(变量,方法) 如:monthSalary,run(),runRun()
3.类:首字母大写,再驼峰命名 如: GoodMan
4.常量:大写+下划线 如: MAX_VALUE
5.尽量不要用拼音命名
1-7、运算符
算数运算符
- , - , * , / ,% , ++, --(前面几个加减乘除就不说了
操作符 | 描述 | 例子 |
---|---|---|
% | 获取两个数据做除法的余数 | B%A等于0 |
++ | 自增: 操作数的值增加1 | B++ 或 ++B 等于 21(区别详见下文) |
– | 自减: 操作数的值减少1 | B-- 或 --B 等于 19(区别详见下文) |
赋值运算符
=、+=,-=,*=,/=,% =
符号 | 作用 | 说明 |
---|---|---|
= | 赋值 | a = 10,将10赋值给变量a |
+= | 加后赋值 | a + = b,将 a + b 的值给a |
- = | 减后赋值 | a - = b,将 a - b的值给a |
* = | 乘后赋值 | a * = b,将a × b 的值给a |
/ = | 除后赋值 | a / = b,将a ÷ b 的商给a |
% = | 取余后赋值 | a % = b,将a ÷b 的余数给a |
关系运算符
==,> , >= , < , <= , != , instanceof
逻辑运算符
&&,||,!
& | 与 |
---|---|
| | 或 |
! | 非(取反) |
^ | 异或(相同为false,不同为true) |
public class Demo {
public static void main(String[] args){
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 */
}
}
位运算符:
&,| , ^ , ~ , >> , << ,>>>(了解!!!!这个是和二进制相关,好处在于运算速度快,效率高)
** 位运算符 示例**
public class Demo06 {
public static void main(String[] args) {
/*
A = 0011 1100
B = 0000 1101
A&B = 0000 1100 // 1 1 为 1
A|B = 0011 1101 // 有一个为1 则为11
~B = 1111 0010
A^B = 0011 0001 // 异或 一样则为0,不一样则为1
2*8 怎么运算最快 2*2*2*2
位运算效率高
<< 左移 *2
>> 右移 /2
0000 0000 0
0000 0010 2
0001 0000 16
*/
System.out.println(2<<3);// 16
}
}
三元运算符:
示例: ? :
public class Demo08 {
public static void main(String[] args) {
// x ? y : z
// 如果x==true,则结果为y,否则结果为z
int score = 80;
String type = score < 60 ? "不及格": "及格";// 必须掌握
// if
System.out.println(type);
}
}
运算符优先级:
1-8、包机制
- 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间
- 包名语句的语法格式为: package pkg1[.pkg2.[pkg3…]]; 如 package Demo;
- 导包格式: import 包名.类名 import package[.package2…].(classname|*) 如 import javax.servlet.ServletException;
- 相同包下的类可以直接访问
- 不同包下的类必须导包,才可以使用
1-9、JavaDoc
-
JavaDoc是Sun公司提供的一个技术,它从程序源代码中抽取类、方法、成员等注释形成一个和源代码配套的API帮助文档。
-
参数信息:
- @auther 作者号
- @version 版本号
- @since 指明需要最早使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
1-10、初识Java内存
Java内存: 堆、栈、方法区
- 堆:
- 存放new的对象和数组
- 可以被所有的线程共享,不会存放别的对象引用
- 栈:
- 存放基本数据类型(会包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在堆里面的具体地址)
- 方法区:
- 可以被所有的线程共享
- 包含了所有的class和static变量
2、流程控制篇
2-1、Scanner
用户交互、基础语法
先new一个scanner对象 Scanner scanner = new Scanner(System.in);
- 然后:
- 首先需要判断输入的是什么类型的值
- 再根据判断输出
- Scanner类中的hasnext()与hasNextLine()通常用在if…else判断中,用来判断是否还有输入的数据 ;
- Scanner类中的next()与nextLine()方法获取接收输入的字符串,在读取前一般需要用 next()和next()
- 同理 nextint(),nextFloat()…
public class Second {
public static void main(String[] agrs){
Scanner scanner=new Scanner(System.in); //重点:注意要加这个 System.in
int a;
System.out.println("请输入您的字符串");
if(scanner.hasNext()){
String i=scanner.nextLine();
System.out.println(i);
}
a=scanner.nextInt();
System.out.println("输出您刚才输入的数字"+a);
scanner.close();
}
}
2-2、顺序结构
程序默认执行的结构,自上而下的执行代码
2-3、分支结构
2-3-1、if
public class Demo01 {
public static void main(String[] args) {
//创建一个扫描对象,用于接收键盘数据
Scanner scanner =new Scanner(System.in);
System.out.println("使用next接收:");
//判断用户是否输入一个数据
if(scanner.hasNext()){
String str=scanner.next();
System.out.println("输入的数据为:"+str);
}
if(scanner.hasNextLine()){
String s=scanner.next();
System.out.println("输出2的数据为:"+s);
}
if(scanner.hasNextInt()){
int a=scanner.nextInt();
System.out.println("输入3的数据为:"+a);
}else {
System.out.println("输入3的数据不为数字,故不输出");
}
//IO流的类若不关闭则回一致占用资源
scanner.close();
}
}
2-3-2、switch
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
default:
语句体3;
break;
}
2-3-3、case穿透
如果switch语句中,case省略了break语句,就会开始case穿透
现象:当开始case穿透,后序的case就不会具有匹配效果,内部的语句都会执行
直到看到break,或者将整体switch语句执行完毕,才会结束
2-4、循环结构
2-4-1、for
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
学习案例1 :求1-100奇数和
int sum = 0;
for(int i = 1; i <= 100;i++){
if(i % 2 != 0){
sum += i;
}
}
System.out.println(sum);
学习案例2 : 在1-100中,遇到数字带7就跳过,其他输出
for(int i=1;i<=100;i++){
int ge=i%10;
int shi=i/10%10;
if(ge !=7 & shi!=7){
System.out.println(i);;
}
}
2-4-2、while
初始化语句;
while(条件判断语句){
循环体语句;
条件控制语句;
}
示例:
public static void main(String[] args) {
//输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果;
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//数字
int m = 0;
while (scanner.hasNextDouble()) {
double x = scanner.nextDouble();
sum = x + sum;
m++;
}
System.out.println("总和为:" + sum);
System.out.println("平均数为:" + (sum /= m));
scanner.close();
}
2-4-3、do while
初始化语句;
do{
循环体语句;
条件控制语句;
}while(条件判断语句);
死循环示例
1.for死循环
public class TestStudent {
public static void main(String[] args) {
for( ; ; ){
System.out.println("无限执行");;
}
}
}
2.while死循环
public class TestStudent {
public static void main(String[] args) {
while(true){
System.out.println("无限执行");
}
}
}
3.do while死循环
public class TestStudent {
public static void main(String[] args) {
do{
System.out.println("无限执行");
}while(true);
}
}
命令提示符窗口中 Ctrl+C 可以结束死循环
>2-4、continue
作用: 跳过某次循环体内容的执行
public class TestStudent {
public static void main(String[] args) {
//电梯从1-20楼,在13楼不停
for(int ele=1;ele<21;ele++){
if(ele==13){
System.out.println("电梯到13楼将不停");
continue;
}
System.out.println("电梯到了:"+ele+"楼,将打开门");
}
}
}
>2-4、break
作用:终止循环体内容的执行
public class Demo {
public static void main(String[] args){
// 模拟20岁工作到80岁,60岁退休
for(int i = 20; i <= 80; i++){
if(i == 60){
break; //结束整个循环
}
System.out.println(i + "岁正在上班");
}
}
}
2-4-4、switch,case
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
default:
语句体3;
break;
}
注:关于case穿透
- 如果switch语句中,case省略了break语句,就会开始case穿透
- 现象:当开始case穿透,后序的case就不会具有匹配效果,内部的语句都会执行
- 直到看到break,或者将整体switch语句执行完毕,才会结束
结合switch case 和break ;案例:减肥计划改进
import java.util.Scanner;
public class Test {
/*
需求:程序运行后,用户可多次查询星期对应的减肥计划,直到输入0,程序结束
步骤:
1. 不明确用户操作几次, 使用死循环包裹业务逻辑
2. 匹配到0的时候,使用break结束循环死循环
*/
public static void main (String[] args){
lo:while(true){
System.out.println("请输入您要查看的星期数:");
System.out.println("(如无需继续查看,请输入0退出程序)");
// 1. 键盘录入星期数据,使用变量接收
Scanner sc = new Scanner(System.in);
int week = sc.nextInt();
// 2. 多情况判断,采用switch语句实现
switch(week){
// 3. 在不同的case中,输出对应的减肥计划
case 0:
System.out.println("感谢您的使用");
break lo;
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;
}
}
}
}
版权声明:本文为CSDN博主「生命是有光的」
额外练习:Random(用于随机数)
import java.util.Random
public class Demo{
/*
Random:产生随机数
1.导包: import java.util.Random;
2.创建对象: Random r = new Random();
r 是变量名,可以变,其他的都不允许改变
3.获取随机数: int numeber = r.nextInt(10);
获取数据的范围:[0,10),包括0,不包括10
number 是变量名,可以变,数字10可以变,其他的不允许变
public static void main(String[] args){
*/
2.创建对象
Random r = new Random();
3.获取随机数
int num = r.nextInt(num);
}
3、数组篇
定义:类似于一个容器,可以存放多个数据
3-1、一维数组
// 格式一:数据类型[] 变量名
int[] array;
// 格式二:数据类型 变量名[]
int array[];
输出:
// 定义了一个int类型的数组,数组名叫arr
int[] arr;
System.out.prinln(arr[]);
3-2、一维数组静态、动态初始化
静态初始化 : 手动指定数组元素,系统会根据元素个数,计算出数组的长度
格式一: 数据类型[] 变量名 = new 数据类型[]{数据1,数据2,数据3,.....}
int[] arr = new int[]{1,2,3};
简化格式: 数据类型[] 变量名 = {数据1,数据2,数据3,....}
int[] arr = {1,2,3};
动态初始化 : 手动指定数组长度,由系统给出默认初始化值
格式: 数据类型[]变量名 = new 数据类型[数组长度];
int[] arr = new int[3];
System.out.println(arr[0]); // 0 系统自动分配的默认初始值
3-3、一维数组示例代码
public class Fourth {
public static void main(String[] args) {
int[] a=new int[10];
System.out.println(a.length); // 得到 10
a[0]=3;
for (int i=0;i<a.length;i++){ //方法一:遍历数组里的数 得到10个数,第一个是3,后面的都是0
System.out.println(a[i]);
}
for(int c : a ){ //方法二:通过增强for遍历数组里的数
System.out.println(c);
}
printT(a); //调用下方的printT方法 输出c数组中的所有值
System.out.println();
int[] reverse = reverse(a); //先将c数组反转后赋值给新建的reverse数组
printT(reverse); //再调用reverse数组给printT方法输出
}
//打印数组元素
public static void printT(int[] nums1){
for (int i=0;i<nums1.length;i++){
System.out.print(nums1[i]+" ");
}
}
//反转数组
public static int[] reverse(int[] r){
int[] result =new int[r.length];
for (int i=0,j=r.length-1; i<r.length ; i++,j--){
result[j]=r[i];
}
return result;
}
}
3-4、二维数组
格式一 :数据类型[][] 变量名;
int[][] arr;
格式二 :数据类型 变量名[][];
int arr[][];
格式三 :数据类型[] 变量名[];
int[] arr[];
3-5、二维数组静态、动态初始化
静态初始化
// 格式: 数据类型[][] 变量名 = new 数据类型[][] {{元素1,元素2...},{元素1,元素2....}};
int[][] arr = new int[][]{{11,22},{33,44}};
// 简化格式
数据类型[][] 变量名 ={{元素1,元素2},{元素1,元素2....}};
int[][] arr ={{11,22},{33,44}};
动态初始化
格式: 数据类型[][] 变量名 = new 数据类型[m][n];
m 表示这个二维数组,可以存放多少个一维数组
n 表示每一个一维数组,可以存放多少个元素
int[][] arr = new int[2][3];
// 该数组可以存放 2 个 一维数组,每个一维数组中可以存放 3 个 int 类型元素
3-6、二维数组示例代码
访问二维数组元素
public class Demo{
public static void main(String[] args){
/*
问题:二维数组中存储的是一维数组,那能不能存入[提前创建好的一维数组]呢?
*/
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};
int[] arr3 = {77,88,99,100};
int[][] arr = new int[3][3];
arr[0] = arr1;
arr[1] = arr2;
arr[2] = arr3;
System.oyt.println(arr[1][2]);
// 66
System.out.println(arr[2][3]);
// 100
}
}
二维数组遍历求和
public static void main(String[] args){
// 1.定义求和变量
int sum = 0;
int[][] arr = {{11,22,33},{44,55,66},{77,88,99}};
// 2.遍历二维数组,获取所有元素
for(int i = 0;i < arr.length;i++){
for(int j = 0;i < arr[i].length;j++){
sum += arr[i][j];
}
}
System.out.println(sum);
}
4、方法篇
4-1、方法的定义
修饰符 返回值 方法名(参数名){return 返回值;}
public static void 方法名(){
//方法体
}
public static void eat(){
//方法体
}
方法分为:静态方法、非静态方法
4-2、方法的调用
如果是调用静态方法,则使用 类名.方法 即可调用成功
如果是调用非静态方法,则需要实例化这个类 new
对象方法( 1.先new一个自己这个对象 A a=new A() 2.再用 对象名.方法名 来调用输出 A.方法名 )
总结理解:
可以看出静态的方法是已经存在了的,所以可以直接进行调用,而非静态的方法不存在,所以需要进行实例化使之存在,才可以进行调用
静态方法 : 加了static
静态方法可以通过 类名.方法名 调用
非静态方法 :没有加static
非静态方法需要通过构造器,new 类名().方法名 才可以调用
注:
- 方法必须先定义后调用
- 方法与方法之间是平级关系,不能嵌套定义
- 方法没有被调用的时候,都在方法区中的字节码文件(.class)中存储
- 方法被调用的时候,需要进入到栈内存中运行
方法参数传递为引用数据类型:传入方法中的,是内存地址
方法的结束 :return
4-3、代码示例
递归
public class Third {
//递归思想
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if (n==1){
return n;
}else {
return n*f(n-1);
}
}
}
设计一个方法可以获取两个数的较大值
import java.util.Scanner;
public class TestStudent {
public static void main(String[] args) {
System.out.println("请输入第一个数字");
Scanner scanner = new Scanner(System.in);
int a,b;
a=scanner.nextInt();
System.out.println("请输入第二个数字");
b=scanner.nextInt();
System.out.println("最大的值为:"+getMax(a,b));
scanner.close();
}
public static int getMax(int a,int b){
if(a>b){
return a;
}else{
return b;
}
}
}
4-4、方法的注意事项
- 方法不能嵌套定义
- 方法的返回值类型为 void 时,表示该方法没有返回值,没有返回值的方法可以省略 return 语句不写。而 如果要编写return,后面不能跟具体的数据,执行不到,属于无效的代码
- return 语句下面,不能编写代码,因为永远执行不到,属于无效的代码
4-5、方法的重载与重写
- 方法的重载(overloade)
发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
- 以下为《Java 核心技术》对重载这个概念的介绍:
综上:重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
- 方法的重写(Override)
重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
- 返回值类型、方法名、参数列表必须相同, 抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
- 如果父类方法访问修饰符为
private/final/static
则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。 - 构造方法无法被重写。
综上:重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变。
图表总结重载与重写的区别:
区别点 | 重载方法 | 重写方法 |
---|---|---|
发生范围 | 同一个类 | 子类 |
参数列表 | 必须修改 | 不可修改 |
方法名称 | 不可修改 | 不可修改 |
返回类型 | 可修改 | 子类方法返回值类型应比父类方法返回值类型更小或相等 |
异常 | 可修改 | 子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等 |
访问修饰符 | 可修改 | 一定不能做更严格的限制(可以降低限制) |
发生阶段 | 编译期 | 运行期 |