JDK,JRE,JVM三者的关系

【Java】部分基础知识汇总_赋值

Java中的数据类型分类

基本数据类型
整数型 byte short int long
浮点型 float double
字符型 char
布尔型 boolean

引用数据类型
字符串、数组、类、接口、Lambda

注意事项:
1. 字符串不是基本类型,而是引用类型。
2. 浮点型可能只是一个近似值,并非精确的值。
3. 数据范围与字节数不一定相关,例如float数据范围比long更加广泛,但是float是4字节,long是8字节。
4. 浮点数当中默认类型是double。如果一定要使用float类型,需要加上一个后缀F。如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L。推荐使用大写字母后缀。

使用变量的注意事项

  1. 如果创建多个变量,那么变量之间的名称不可以重复。
  2. 对于float和long类型来说,字母后缀F和L不要丢掉
  3. 如果使用byte或者short类型的变量,那么右侧的数据值不能超过左侧类型的范围。
  4. 没有进行赋值的变量,不能直接使用;一定要赋值之后,才能使用。
  5. 变量使用不能超过作用域的范围。
    【作用域】:从定义变量的一行开始,一直到直接所属的大括号结束为止。
  6. 可以通过一个语句来创建多个变量,但是一般情况不推荐这么写。

自动类型转换与强制类型转换

自动类型转换:数据范围从小到大
强制类型转换:数据范围从大到小

//自动类型转换
// 左边是float类型,右边是long类型,左右不一样
// long --> float,范围是float更大一些,符合从小到大的规则

float num3 = 30L;
System.out.println(num3); // 30.0

//强制类型转换
1. 特点:代码需要进行特殊的格式处理,不能自动完成。
2. 格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;

//强制类型转换注意事项:
1. 强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出。
2. byte/short/char这三种类型都可以发生数学运算,例如加法“+.
3. byte/short/char这三种类型在运算的时候,都会被首先提升成为int类型,然后再计算。
4. boolean类型不能发生数据类型转换

//char类型数学运算
char zifu1 = 'A'; // 这是一个字符型变量,里面是大写字母A
System.out.println(zifu1 + 1); // 66,也就是大写字母A被当做65进行处理
// 计算机的底层会用一个数字(二进制)来代表字符A,就是65
// 一旦char类型进行了数学运算,那么字符就会按照一定的规则翻译成为一个数字

//强制类型转换示例
byte num4 = 40; // 注意!右侧的数值大小不能超过左侧的类型范围
short num6 = 60;
// byte + short --> int + int --> int
// int强制转换为short:注意必须保证逻辑上真实大小本来就没有超过short范围,否则会发生数据溢出
short result2 = (short) (num4 + num6);
System.out.println(result2); // 100

注意以下情况不是自动类型转换,而是javac编译器自动处理的

/*
对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,
那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char)。

1. 如果没有超过左侧的范围,编译器补上强转。
2. 如果右侧超过了左侧范围,那么直接编译器报错。
*/
public class Demo12Notice {
public static void main(String[] args) {
// 右侧确实是一个int数字,但是没有超过左侧的范围,就是正确的。
// int --> byte,不是自动类型转换
byte num1 = /*(byte)*/ 30; // 右侧没有超过左侧的范围
System.out.println(num1); // 30

// byte num2 = 128; // 右侧超过了左侧的范围

// int --> char,没有超过范围
// 编译器将会自动补上一个隐含的(char)
char zifu = /*(char)*/ 65;
System.out.println(zifu); // A
}
}

编译器的常量优化

/*
在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量,
那么编译器javac将会直接将若干个常量表达式计算得到结果。
short result = 5 + 8; // 等号右边全都是常量,没有任何变量参与运算
编译之后,得到的.class字节码文件当中相当于【直接就是】:
short result = 13;
右侧的常量结果数值,没有超过左侧范围,所以正确。

这称为“编译器的常量优化”。

但是注意:一旦表达式当中有变量参与,那么就不能进行这种优化了。
*/
public class Demo13Notice {
public static void main(String[] args) {
short num1 = 10; // 正确写法,右侧没有超过左侧的范围,

short a = 5;
short b = 8;
// short + short --> int + int --> int
// short result = a + b; // 错误写法!左侧需要是int类型

// 右侧不用变量,而是采用常量,而且只有两个常量,没有别人
short result = 5 + 8;
System.out.println(result);

//short result2 = 5 + a + 8; // 报错,结果不是18,因为有变量参与
}
}

Char类型与ASCII码表

/*
数字和字符的对照关系表(编码表):

ASCII码表:American Standard Code for Information Interchange,美国信息交换标准代码。
Unicode码表:万国码。也是数字和符号的对照关系,开头0-127部分和ASCII完全一样,但是从128开始包含有更多字符。

48 - '0'
65 - 'A'
97 - 'a'
*/

char zifu2 = 'A'; // 其实底层保存的是65数字
char zifu3 = 'c';
// 左侧是int类型,右边是char类型,
// char --> int,确实是从小到大
// 发生了自动类型转换
int num = zifu3;
System.out.println(num); // 99

自加与自减

/*
自增运算符:++
自减运算符:--

基本含义:让一个变量涨一个数字1,或者让一个变量降一个数字1
使用格式:写在变量名称之前,或者写在变量名称之后。例如:++num,也可以num++
使用方式:
1. 单独使用:不和其他任何操作混合,自己独立成为一个步骤。
2. 混合使用:和其他操作混合,例如与赋值混合,或者与打印操作混合,等。
使用区别:
1. 在单独使用的时候,前++和后++没有任何区别。也就是:++num;和num++;是完全一样的。
2. 在混合的时候,有【重大区别】
A. 如果是【前++】,那么变量【立刻马上+1】,然后拿着结果进行使用。 【先加后用】
B. 如果是【后++】,那么首先使用变量本来的数值,【然后再让变量+1】。 【先用后加】

注意事项:
只有变量才能使用自增、自减运算符。常量不可发生改变,所以不能用。
*/

int x = 10;
int y = 20;
// 11 + 20 = 31
int result3 = ++x + y--;
System.out.println(result3); // 31
System.out.println(x); // 11
System.out.println(y); // 19

比较运算符和逻辑运算符

//比较运算符
int num1 = 10;
int num2 = 12;
System.out.println(num1 < num2); // true

//逻辑运算符
System.out.println(true && false); // false
// true && true --> true
System.out.println(3 < 4 && 10 > 5); // true

三元运算符

三元运算符的格式为​​(关系表达式) ? 表达式1 : 表达式2;​

//三元运算符示例
int x = 10;
int y = 5;
int z;
z = (x > y) ? x : y;

Switch语句的注意事项

/*
switch语句使用的注意事项:

1. 多个case后面的数值不可以重复。

2. switch后面小括号当中只能是下列数据类型:
基本数据类型:byte/short/char/int
引用数据类型:String字符串、enum枚举

3. switch语句格式可以很灵活:前后顺序可以颠倒,而且break语句还可以省略。
“匹配哪一个case就从哪一个位置向下执行,直到遇到了break或者整体结束为止。”
*/
public class Demo08SwitchNotice {
public static void main(String[] args) {
int num = 2;
switch (num) {
case 1:
System.out.println("你好");
break;
case 2:
System.out.println("我好");
// break;
case 3:
System.out.println("大家好");
break;
default:
System.out.println("他好,我也好。");
break;
} // switch
}
}

方法的重载

/*
对于功能类似的方法来说,因为参数列表不一样,却需要记住那么多不同的方法名称,太麻烦。

方法的重载(Overload):多个方法的名称一样,但是参数列表不一样。
好处:只需要记住唯一一个方法名称,就可以实现类似的多个功能。

方法重载与下列因素相关:
1. 参数个数不同
2. 参数类型不同
3. 参数的多类型顺序不同

方法重载与下列因素无关:
1. 与参数的名称无关
2. 与方法的返回值类型无关
*/
public class Demo01MethodOverload {

public static void main(String[] args) {
/*System.out.println(sumTwo(10, 20)); // 30
System.out.println(sumThree(10, 20, 30)); // 60
System.out.println(sumFour(10, 20, 30, 40)); // 100*/

System.out.println(sum(10, 20)); // 两个参数的方法
System.out.println(sum(10, 20, 30)); // 三个参数的方法
System.out.println(sum(10, 20, 30, 40)); // 四个参数的方法
// System.out.println(sum(10, 20, 30, 40, 50)); // 找不到任何方法来匹配,所以错误!

sum(10, 20);
}

public static int sum(int a, double b) {
return (int) (a + b);
}

public static int sum(double a, int b) {
return (int) (a + b);
}

public static int sum(int a, int b) {
System.out.println("有2个参数的方法执行!");
return a + b;
}

// 错误写法!与方法的返回值类型无关
// public static double sum(int a, int b) {
// return a + b + 0.0;
// }

// 错误写法!与参数的名称无关
// public static int sum(int x, int y) {
// return x + y;
// }

public static int sum(double a, double b) {
return (int) (a + b);
}

public static int sum(int a, int b, int c) {
System.out.println("有3个参数的方法执行!");
return a + b + c;
}

public static int sum(int a, int b, int c, int d) {
System.out.println("有4个参数的方法执行!");
return a + b + c + d;
}

}

数组的静态初始化与动态初始化

动态初始化:指定长度
静态初始化:指定内容

//动态初始化
// 格式:数据类型[] 数组名称 = new 数据类型[数组长度];
int[] arrayA = new int[300];

// 创建一个数组,能存放10个double类型的数据
double[] arrayB = new double[10];

// 创建一个数组,能存放5个字符串
String[] arrayC = new String[5];

//静态初始化
// 直接创建一个数组,里面装的全都是int数字,具体为:5、15、25
int[] arrayA = new int[] { 5, 15, 25, 40 };

// 创建一个数组,用来装字符串:"Hello"、"World"、"Java"
String[] arrayB = new String[] { "Hello", "World", "Java" };

// 省略格式的静态初始化
int[] arrayA = { 10, 20, 30 };

//直接打印数组名,是打印数组所在的哈希地址
System.out.println(arrayA); // [I@75412c2f

所有的引用类型变量,都可以赋值为一个null值

/*
所有的引用类型变量,都可以赋值为一个null值。但是代表其中什么都没有。

数组必须进行new初始化才能使用其中的元素。
如果只是赋值了一个null,没有进行new创建,
那么将会发生:
空指针异常 NullPointerException

原因:忘了new
解决:补上new
*/
public class Demo02ArrayNull {

public static void main(String[] args) {
int[] array = null;
// array = new int[3];
System.out.println(array[0]);
}

}

局部变量和成员变量

  1. 定义位置不同
    局部变量:在方法的内部
    成员变量:在方法的外部,直接写在类当中
  2. 作用范围不同
    局部变量:只有方法当中才可以使用,出了方法就不能再用
    成员变量:整个类全都可以通用
  3. 默认值不同
    局部变量:没有默认值,如果想使用,必须手动进行赋值
    成员变量:如果没有赋值,会有默认值,规则和数组一样
  4. 内存的位置不同
    局部变量:位于栈内存
    成员变量:位于堆内存
  5. 生命周期不一样
    局部变量:随着方法进栈而诞生,随着方法出栈而消失
    成员变量:随着对象创建而诞生,随着对象被垃圾回收而消失
public class Demo01VariableDifference {

String name; // 成员变量

public void methodA() {
int num = 20; // 局部变量
System.out.println(num);
System.out.println(name);
}

public void methodB(int param) { // 方法的参数就是局部变量
// 参数在方法调用的时候,必然会被赋值的。
System.out.println(param);

int age; // 局部变量
// System.out.println(age); // 没赋值不能用

// System.out.println(num); // 错误写法!
System.out.println(name);
}

}

private关键字

只能在本类中访问用该关键字修饰的变量

方法的局部变量和类的成员变量重名时

根据就近原则,优先使用局部变量,如果需要访问本类当中的成员变量,需要使用格式​​this.成员变量名​

public class test2 {
String name;
public void sayhello(String name){
System.out.println(name+"你好"+this.name);
}
}

构造方法

当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值,构造方法的写法上,方法名与它所在的类名相同。它没有返回值,所以不需要返回值类型,甚至不需要void

注意事项

  1. 如果你不提供构造方法,系统会给出无参数构造方法。
  2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
  3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
public class Student {

// 成员变量
private String name;
private int age;

// 无参数的构造方法
public Student() {
System.out.println("无参构造方法执行啦!");
}

// 全参数的构造方法
public Student(String name, int age) {
System.out.println("全参构造方法执行啦!");
this.name = name;
this.age = age;
}

// Getter Setter
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;
}

}

标准代码——JavaBean

JavaBean 是 Java语言编写类的一种标准规范。符合 JavaBean 的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的 set 和 get 方法。

public class ClassName{ 
//成员变量
//构造方法
//无参构造方法【必须】
//有参构造方法【建议】
//成员方法
//getXxx()
//setXxx()
}
//示例代码
public class Student {
//成员变量
private String name;
private int age;

//构造方法
public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = 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;
}
}

匿名对象

/*
创建对象的标准格式:
类名称 对象名 = new 类名称();

匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。
new 类名称();

注意事项:匿名对象只能使用唯一的一次,下次再用不得不再创建一个新对象。
使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。
*/
public class Demo01Anonymous {

public static void main(String[] args) {
// 左边的one就是对象的名字
Person one = new Person();
one.name = "高圆圆";
one.showName(); // 我叫高圆圆
System.out.println("===============");

// 匿名对象
new Person().name = "赵又廷";
new Person().showName(); // 我叫:null
}
}
public class Person {

String name;

public void showName() {
System.out.println("我叫:" + name);
}

}

使用匿名对象传参

import java.util.Scanner;

public class Demo02Anonymous {

public static void main(String[] args) {
// 普通使用方式
// Scanner sc = new Scanner(System.in);
// int num = sc.nextInt();

// 匿名对象的方式
// int num = new Scanner(System.in).nextInt();
// System.out.println("输入的是:" + num);

// 使用一般写法传入参数
// Scanner sc = new Scanner(System.in);
// methodParam(sc);

// 使用匿名对象来进行传参
// methodParam(new Scanner(System.in));

Scanner sc = methodReturn();
int num = sc.nextInt();
System.out.println("输入的是:" + num);
}

public static void methodParam(Scanner sc) {
int num = sc.nextInt();
System.out.println("输入的是:" + num);
}

public static Scanner methodReturn() {
// Scanner sc = new Scanner(System.in);
// return sc;
return new Scanner(System.in);
}

}