自己在哔哩哔哩上面跟着黑马学习Java的笔记
目录
1.JDK是什么?有哪些内容组成?JRE是什么?有哪些内容组成?
一、JDK和JRE
1.JDK是什么?有哪些内容组成?JRE是什么?有哪些内容组成?
JDK是Java开发工具包,包含了 JVM虚拟机(Java程序运行的地方)、核心类库(Java已经写好的东西,我们可以直接使用)、开发工具(javac、java、jdb、jhat...)。
JRE是Java运行环境,包含了JVM、核心类库、运行工具。
2.JDK,JRE,JVM包含关系是什么?
JDK包含JRE,JRE包含JVM。
二、关于编写代码的知识点
1.关于注释
单行注释://注释信息;多行注释:/*注释信息*/;文档注释:/**注释信息**/
2.关键字
什么是关键字? 被Java赋予了特定含义的单词。(关键字全部小写,常见的代码编辑器中会高亮显示)
第一个关键字——class:用于创建/定义一个类,类是Java最基本的组成单元。
3.字面量
字面量类型:整型类型(1,2),小数类型(13.14),字符串类型("hello"),字符类型('A' 内容只能有一个),布尔类型(true,false),空类型(null,null不能直接打印)。
\t 制表符:在打印时,把前面的字符串长度补齐到8,或者8的整数倍。最少补1,最多补8。
System.out.println("name"+ '\t' + "age")
4.变量
变量是有可能发生改变的量。
变量在使用前一定要赋值。//建议:以后在定义变量的时候,请直接赋值,不要把赋值分开写。
定义格式: 数据类型 变量名 = 数据值;
数据类型:为空间中存储的数据,加入类型[限制];变量名:就是存储空间的名字(方便以后使用);数据值:真正存在数据中的值;等号:赋值,把右边的数据赋值给左边的变量。
int a = 10;
System.out.println(a);
5.计算机存储
在Java中
二进制:由0和1组成,代码中以0b开头。
十进制:由0~9组成,前面不加任何前缀。
八进制:由0~7组成,代码中以0开头。
十六进制:由0~9,a~f组成,代码中以0x开头。
System.out.println(17);//十进制
System.out.println(017);//八进制
System.out.println(0b123);//语法错误
System.out.println(0x123);//十六进制
//在以前,计算机的二进制是有孔和没孔(在纸带上),现在是高电压和低电压。
5.1任意进制转十进制
公式:系数 * 基数的权次幂 相加
系数:就是每一位上的数;基数:当前的进制数;权:从右往左,依次为0 1 2 3 4 5 ...
eg: 二进制101------------十进制:1*2^2+0*2^1+1*2^0=5
八进制101------------十进制:1*8^2+0*8^1+1*8^0=65
十六进制abc---------十进制:10*16^2+11*16^1+12*16^0=2748
5.2二进制转十进制(8421方法)
8421方法:1-128 1-64 1-32 1-16 1-8 1-4 1-2 1-1
eg:1 1 0(不转) 1 = 8 + 4 + 不转 + 1 =13
三、Java基础知识
1.数据类型
数据类型的分类:基本数据类型、引用数据类型。
1.1基本数据类型(黑马程序课程)
1.2 !!!long:
如果要定义long类型的变量,在数据值的后面需要加一个L作为后缀,L可以是大写的,也可以是小写的。(建议大写)
long n = 99999999999L;
System.out.prinltn(n);
1.3 !!!float:
定义float类型变量的时候,数据值也需要加一个F作为后缀。
float n = 10.1F;
System.out.prinltn(n);
2.标识符
- 由数字、字母、下划线(_)和美元符($)组成
- 不能以数字开头
- 不能是关键字
- 区分大小写
- 软性建议:小驼峰命名法:方法、变量 eg:name firstName
- 大驼峰命名法:类名 eg:Student GoodStudent
3.键盘录入
Scanner类:java帮我们写好的一个类,这个类可以接受键盘输入的数字。(sc.nextInt(););
四、运算符
1.算术运算符
+加 -减 *乘 /除 %取模
!!!!整数参与计算,得出的结果只能是整数
!!!!小数参与计算,结果可能不是准确的,如果我们需要精确计算,那我们需要后面的知识点。
!!!!取模做的是除法,获取的是余数。
1.1数字相加
隐式转换(自动类型提升):把一个取值范围小的数值,转成取值范围大的数据(补0)
int a = 10;
double b = a;
!!!取值范围:byte(取值范围最小)<short<int<long<float<double(取值范围最大)
!!!当数字进行运算的时候,数据类型不一样不能运算,需要转成一样的,才能继续运算
!!!byte short char 三种类型的数据在运算的时候,都会直接先提升为int,然后再进行运算。
!!!取值范围小的,和取值范围大的进行运算,小的会先提升为大的,再进行运算。
强制转换:如果把一个取值范围大的数值,赋值给取值范围小的变量,是不允许直接赋值的。如果一定要这么做就需要加入强制转换。(去0所以会丢失精度)
格式: 目标数据类型 变量名 = (目标数据类型)被强转的数据;
double a = 12.3;
int b = (int) a;
!!!数据比较大,强转的时候可能就会出错。
byte b1 = 10;
byte b2 = 20;
byte result = (byte)(b1+b2);
1.2字符串相加
!!!当"+"操作中出现字符串时,这个"+"是字符串连接符,而不是算术运算符。会将前后的数据进行拼接,产生新的字符串。
eg: "123"+123---------会出现"123123"
!!!连续进行"+"操作的时候,从左到右逐个进行。
eg:1 + 99 + "黑马"-------会出现"100黑马"
System.out.println(3.7 + "abc");//"3.7abc"
System.out.println("abc" + true);//"abctrue"
System.out.println('中' + "abc" + true);//"中abctrue"
int age = 18;
System.out.println("我的年龄是" + age + "岁");//"我的年龄是18岁"
System.out.println("我的年龄是" + "age" + "岁");//"我的年龄是age岁"
System.out.println(1 + 2 + "abc" + 2 + 1 );//"3abc21"
1.3字符相加
当 字符+字符/字符+数字 时,会把字符通过ASCII码表查询到的对应的数字再进行计算。
System.out.println(1 + 'a');//98
System.out.println('a' + "abc");//aabc
2.自增自减运算符
++ 加 --减
++/--无论放在前面还是后面,单独写一行的结果都是一样的。
3.赋值运算符
eg:
//+=,-=,*=,/=,%=底层都有隐藏了一个强制类型转换
short s = 1 ;
//把左边和右边进行相加,得到结果2,再赋值给左边的变量
s += 1;
//相当于:s = (short) (s + 1);
System.out.println(s);//2
!!!+=,-=,*=,/=,%=底层都有隐藏了一个强制类型转换
4.关系运算符
!!!关系运算符的结果都是boolean类型,要么true,要么false。
5.逻辑运算符
在Java中,需要把式子先进行拆解,在进行合并表达。
短路逻辑运算符
&& 短路与 左边为false,右边不管是真是假,整个表达式都是false。
|| 短路或 左边为true,右边不管是真是假,整个表达式的结果一定是true。
&| 无论左边true还是false,右边都要执行。6.
&&|| 如果左边能确定整个表达式的结果,右边不执行。
6.三元运算符
格式:关系表达式 ? 表达式1 : 表达式2
eg:求两个数的较大值 int max = a > b ? a : b;
计算规则:首先计算关系表达式的值;如果值为true,表达式1的值就是运算结果;如果值为false,表达式2的值就是运算结果
五、原码反码补码
原码:十进制数据的二进制表现形式,最左边是符号为,0为正,1为负。(bit比特位);利用原码对正数进行计算是没有问题的
原码的弊端:如果进行负数的计算,结果就会出错,与我们预期的就是相反的。
一个字节(计算机最小的存储单位)=8个bit
一个字节的最大值:0(正)1111111——+127;一个字节的最小值:1(负)1111111——-127
反码:为了解决原码不能计算负数的问题而出现的
计算规则:正数的反码不变,负数的反码在原码的基础上,符号不变,取值相反,0变1,1变0。
反码的弊端:负数在运算的时候,如果结果不跨过0,是没有任何问题的,但如果结果跨0,跟实际结果会有1的偏差。
补码:为了解决负数计算时跨0的问题而出现的
补码的计算规则:正数的补码不变,负数的补码在反码的基础上再加1;另外补码还能多记录一个特殊的值-128,该数据在1个字节下,没有反码和原码。
补码的注意点:计算机中的存储和计算都是以补码的形式进行的
左移一次相当于原数值*2;右移一次相当于原数值/2
六、流程控制语句
1.顺序结构
从上往下依次运行
2.分支结构
2.1if语句
if语句的第一种格式
//格式1
if(关系表达式){
语句体;
}
//格式2
if(关系表达式){
语句体1;
}else{
语句体2;
}
//格式3
if(关系表达式){
语句体1;
}else{
语句体2;
}
...
else{
语句体 n + 1;
}
!!!如果对一个布尔类型的变量进行判断,不要用==,直接把变量写在小括号中。
boolean isLightGreen = false;
boolean isLightYellow = false;
boolean isLightRed = true;
if(isLightGreen){
System.out.ptintln("gogogo!");
}
if(isLightYellow){
System.out.ptintln("slow!");
}
if(isLightRed){
System.out.ptintln("stop!");
}
2.2switch语句
//格式
switch(表达式){
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
!!!default可以省略,循环不会有问题,但建议别省略;default不一定非得写最下面,但习惯写下面。
!!!break不能省略,否则case会往下穿透,程序会继续执行。
!!!在JDK12中可以简化switch的语句用-> eg: case 值 -> System.out.println(" ");
3.循环语句
3.1for循环
/*
for循环格式
for(初始化语句;条件判断语句;条件控制语句){
循环体语句;
}
*/
public class Main {
public static void main(String[] args) {
int count = 0;
Scanner sc = new Scanner(System.in);
int start = sc.nextInt();
int end = sc.nextInt();
for(int i = start;i<=end;i++){
if (i%3==0 && i%5==0){
count++;
}
}
System.out.println(count);
}
}
3.2while
/*
while循环语句格式
初始化语句;
while(条件判断语句){
循环体语句;
条件控制语句;
}
*/
public class Main {
public static void main(String[] args) {
int i = 1;
while(i<=100){
System.out.println(i);
i++;
}
}
}
3.3for和while的对比
相同点: 运行规则都是一样的。
区别:for循环中是知道循环次数或者循环的范围;while循环中是不知道循环的次数和范围,只知道循环的结束条件。
public class Main {
public static void main(String[] args) {
int count = 0;
double a = 0.1;
while (a<=8844430){
a = a*2;
count++;
}
System.out.println(count);
}
}
3.4例题
力扣例题:回文数
public class Main {
public static void main(String[] args) {
int num = 0;
int x = 1212121;
int temp = x;
while(x!=0){
int ge = x % 10;
x = x / 10;
num = num * 10 + ge;
}
System.out.println(num);
System.out.println(num == temp);
}
}
力扣例题:求商和余数
package Excise;
public class test1 {
public static void main(String[] args){
int dividend = 100;
int divisor = 10;
int count = 0;
while(dividend>=divisor){
dividend = dividend - divisor;
count++;
}
System.out.println("余数为"+ dividend);
System.out.println("商为" + count);
}
}
3.5do...while
先执行后判断
/*格式*/
初始化语句;
do{
循环体语句;
条件控制语句;
}
while(条件判断语句);
4.高级循环
4.1无限循环
//for
for(;;){
System.out.println("学习");
}
//while
while(true){
System.out.println("学习");
}
//do
do{
System.out.println("学习");
}
while(true);
!!!无线循环的下面不能再写其他代码了,因为循环永远停不下来,那么下面的代码永远执行不到。
4.2跳转控制语句
continue:结束本次循环,继续下次的循环
break:结束整个循环
package Excise;
public class test1 {
public static void main(String[] args){
//5.fori可以快速写出for循环语句
for (int i=1; i<=5 ; i++){
if (i ==3){
//结束本次循环,继续下次的循环
continue;
}
System.out.println("老虎吃包子"+ i);
}
}
}
4.3练习
4.3.1平方根
package Excise;
import java.util.Scanner;
public class test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数");
int number = sc.nextInt();
for (int i = 0; i < number; i++) {
if (i*i==number){
System.out.println(i+"是"+number+"的平方根");
break;
}
else if (i * i>number){
System.out.println((i-1)+"就是"+number+"平方根的整数部分");
break;
}
}
}
}
4.3.2逢七过
package Excise;
public class test1 {
public static void main(String[] args) {
for (int i = 1;i<100;i++){
if(i%10==7 || i%7==0 || i/10%10==7){
System.out.println("过");
continue;
}
System.out.println(i);
}
}
}
4.3.3求质数
package Excise;
import java.util.Scanner;
public class test1 {
public static void main(String[] args) {
//质数只能被它自己和1整除,那么这个数字就是质数
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个正整数");
int x = sc.nextInt();
boolean flag = true;//将它本身认为是一个质数
for (int i = 2; i < x; i++) {
if (x%i==0 ){
flag=false;//有数字可以整数,那这个数就不是质数
break;
}}
//只有当这个循环结束了,表示这个范围之内的所有数字都判断完毕了;
//此时才能判断x是一个质数
if (flag){
System.out.println(x+"是质数");
}else {
System.out.println(x+"不是质数");
}}
}
4.3.4猜数字
!!!Random r = new Random();
package Excise;
import java.util.Random;
import java.util.Scanner;
public class test1 {
public static void main(String[] args) {
Random r = new Random();
//在小括号中,书写的是生成随机数的范围
//这个范围一定是从0开始的
//到这个数-1结束
//口诀:包头不包尾,包左不包右
int number = r.nextInt(100)+1;
//不能写在循环的里面,否则每次都会生成一个新的随机数
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请输入您猜的数字:");
int guessNumber = sc.nextInt();
if (guessNumber < number){
System.out.println("猜小了");
}else if (guessNumber > number){
System.out.println("猜大了");
}else {
System.out.println("猜对啦!");
break;
}
}
}
}
七、数组
什么是数组?
数组指的是一种容器,可以用来存储同种数据类型的多个值(数组容器在存储数据的时候,需要结合隐式转换考虑)
数组的定义
1. 数据类型 [ ] 数组名 eg:int [ ] array
2.数据类型 数据名 [ ] eg:int array[ ]
数组的初始化:
1.静态初始化:就是在内存中,为数据容器开辟空间,并将数据存入容器中的过程。
数据类型 [ ] 数据名 = new 数据类型 [ ]{元素1,元素2,元素3.... };
eg:int[] array = new int[ ]{11,22,33};
package Excise;
public class test1 {
public static void main(String[] args) {
//需求1:定义数组存储5个学生的年龄
int[] arr1 = new int[]{11,1,2,3,4};
int[] arr2 = {11,12,13,14};
//需求2:定义数组存储三个学生的姓名
String[] arr3 = new String[]{"111","2222","3333"};
String[] arr4 = {"111","222","333"};
//需求3:定义数组存储4个学生的身高1.93
double[] arr5 = new double[]{1.92,2.1,2.2,2.3};
double[] arr6 = {1.92,2.1,2.2,2.3};
}
}
地址值的格式含义:[D@776ec8df
[ :表示当前是一个数组值。
D:表示当前数组里面的元素都是double类型的
@:表示一个间隔符号(固定格式)
776ec8df:才是数组真正的地址值。16进制
2.动态初始化:初始化时只指定数组的长度,由系统为数组分配初始值。
格式:数据类型[ ] 数组名 = new 数组类型[数组长度];
!!!整数类型:默认初始化值为0;
!!!小数类型:默认初始化值为0.0;
!!!字符类型:默认初始化值为'/u0000'空格;
!!!布尔类型:默认初始化值false;
!!!引用数据类型:默认初始化值null;
3.静态初始化与动态初始化的区别:
动态初始化:一般用于,只明确元素的个数,不明确具体的数值,推荐使用动态初始化。eg:用户从键盘录入等。
静态初始化:一般用于,已经明确了要操作的具体数值,直接静态初始化即可。eg:已知的学生成绩等。
数组的访问:
格式: 数组名[索引]
把数据存储到数组当中去: 格式:数组名[索引] = 具体的数据或者变量; 一旦覆盖,原本的数据就没有了。
数组的遍历练习:
不要浅显的认为遍历就是打印一便,遍历其实是把数组里的值都访问一便。
1
package Excise;
public class test1 {
public static void main(String[] args) {
int count = 0;
int [ ] arr = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < arr.length; i++) {
if (arr[i]%3==0){
count++;
}
}System.out.println("有"+count+"个");
}
}
2.变化数据
package Excise;
public class test1 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 0) {
arr[i] = arr[i] / 2;
} else {
arr[i] = arr[i] * 2;
}
}
}
}
数组的练习
1.求最大值
package Excise;
public class test1 {
public static void main(String[] args) {
//定义数组
int[] arr = {33,5,22,44,55};
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i]>max){
max = arr[i];
}
}
System.out.println(max);
}
}
2.遍历数组并求和、求平均值、求比平均数小的值
package Excise;
import java.util.Random;
public class test1 {
public static void main(String[] args) {
int[] arr = new int[10];
Random r = new Random();
for (int i = 0; i < arr.length; i++) {
int number = r.nextInt(100)+1;
arr[i] = number;
}
//求随机数的和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum = sum+ arr[i];
}
System.out.println("所有数据的和为"+sum);
//求所有数据的平均值
int avg = sum / arr.length;
System.out.println("所有数据的平均值为"+avg);
//求多少个数据比平均值少
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i]<avg){
count++;
}
}
System.out.println("有"+count+"个数据比平均值小");
}
}
3.交换数组中的数据
package Excise;
//交换两个数值的值
public class test1 {
public static void main(String[] args) {
int a = 1;
int b = 2;
int temp = a;
a=b;
b=temp;
System.out.println(a);
System.out.println(b);
}
}
3.1交换首尾索引对应的元素
package Excise;
//交换首尾索引对应的元素
public class test1{
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
for (int i = 0,j = arr.length-1;i < j ;j--,i++) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
4.打乱数组中的数据
package Excise;
import java.util.Random;
public class test1{
public static void main(String[] args){
//难点:如何获取数组中的随机索引
int [] arr = {1,2,3,4,5};
//循环遍历数组,从0索引开始打乱数据的顺序
Random r = new Random();
for (int i = 0; i < arr.length ;i++) {
//生成一个随机索引
int randomIndex = r.nextInt(arr.length);
//用随机索引指向的元素跟i指向的元素进行交换
int temp = arr[i];
arr[i] = arr[randomIndex];
arr[randomIndex] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
数组内存图
栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行。逐行执行;
堆:存储对象或者数组,new来创建,都存储在堆内存。(数组)
方法区:存储可以运行的class文件。
本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关。
寄存器:给CPU使用,和我们开发无关。
总结:只要是new出来的就一定时在堆里面开辟了一个小空间;如果new了多次,那么在堆里面游多个小空间,每个小空间中都有各自的数据;当两个数组指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次访问的时候都是修改之后的结果了。