常量:在程序运行期间,固定不变的量
常量的分类:
- 字符串常量:凡是用双引号引起来的部分,叫做字符串常量,例如:"abc", "hello", "123"
- 整数常量:直接写上的数字,没有小数点,例如:100, 200, 0, -250
- 浮点数常量:直接写上的数字,有小数点,例如:2.5, -3.14, 0.0
- 字符串常量:凡是用单引号引起来的单个字符,就是字符常量,例如:'a', 'b', '1', '我'(中文也代表一个字符)
- 布尔常量:true,false
- 空常量:null,代表没有任何数据
demo:
// 常量的输出
public class DemoConstant {
    public static void main(String[] args) {
        // 字符串常量
        System.out.println("ABC");
        System.out.println("");
        // 整数常量
        System.out.println(30);
        System.out.println(-10);
        // 字符常量
        System.out.println('A');
        System.out.println('我');
        // 布尔常量
        System.out.println(true);
        System.out.println(false);
        
        // 空常量,空常量不能拿来打印输出
//        System.out.println(null);
    }
}
变量
程序运行期间,内容可以发生变化的量
创建一个变量的两种形式:
// 先创建再赋值
int num;
num = 20;
// 直接创建加赋值
int num = 100;
变量使用注意事项:
- 如果创建多个变量,那么变量之间的名称不可以重复
- 对于 float 和 long 类型来说,字母后缀 F 和 L 不能丢掉
- 如果使用 byte 或 short 类型的变量,那么右侧的数据值不能超过左侧的类型
- 变量一定要赋值之后,才能使用,并不能超过作用域的范围,【作用域】:从定义变量的一行开始,一直到直接所属的大括号结束为止
demo:
public class Variable {
    public static void main(String[] args) {
        int a = 10;
        System.out.println("a: " + a);
        {
            int b = 20;
            System.out.println("b: " + b);
        }
//        System.out.println(b);  // 已经超出了作用域范围
        // 同时创建变量并赋值
        int c = a;
        System.out.println("c: " + c);
    }
}
基本数据类型(四类八种)
- 整数型:byte, short, int, long
- 浮点型:float, double
- 字符型:char
- 布尔型:boolean
数据类型
关键字
内存占用(字节)
取值范围
字节型
byte
1
-128 ~ 127
短整型
short
2
-32768 ~ 32767
整型
int(默认)
4
-2^31 ~ 2^31-1
长整型
long
8
-2^63 ~ 2^63-1
单精度浮点型
float
4
比long范围广
双精度浮点型
double
8
最大
字符型
char
2
0 ~ 65535
布尔类型
boolean
1
true, false
注意事项:
- 字符串不是基本数据类型,是引用类型
- 浮点型可能是一个近似值,并非精确的值
- 数据范围与字节数不一定相关,有特例,例如 float 数据范围比 long 更加广泛,但只有 4 个字节
- 浮点数默认类型是 double,如果一定要使用 float 类型,需要加F
- 整数默认类型是 int,如果一定要使用 long 类型,需要加L,推荐使用大写:System.out.println(100L)
引用数据类型:字符串,数组,类,接口,Lambda
略
数据类型转换
当数据类型不一样时,将会发生数据类型转换,分为自动类型转换(隐式) 和 强制类型转换(显式)
1)自动类型转换(隐式):
代码不需要进行特殊处理,自动完成,规则:数据范围从小到大(左边大,右边小)
public class DataType{
    public static void main(String[] args){
        // 左边是long类型, 右边是默认的int类型,符合了数据范围从小到大的要求,发生了自动转换
        long num1 = 10;
        System.out.println(num1);  // 10
        // 左边是默认的double类型,右边是声明的float类型,符合从小到大的规则,也发生了自动类型转换
        double num2 = 2.5F;
        System.out.println(num2);  // 2.5
        // 左边是float类型,右边是long类型,也发生了自动转换
        float num3 = 30L;
        System.out.println(num3);  // 30.0
    }
}
2)强制类型转换(显式):
代码需要进行特殊格式处理,不能自动完成,格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的值
强制类型转换一般不推荐使用,因为有可能发生 数据溢出 和 精度损失
byte / short / char 这三种类型都可以发生数学运算,比如做加法,在运算的时候,都会被首先提升为 int 类型,然后再计算
boolean 类型不能发生数据类型转换(与python不同)
public class DataType{
    public static void main(String[] args){
        System.out.println("=");
        // 左边是int类型,右边是long类型,不符合从小到大的要求,需要强制转换
        int num1 = (int) 100L;  // 100L在某些情况下可以是超过int范围的
        System.out.println(num1);  // 10
        // 数据溢出的情况
        int num2 = (int) 6000000000L;
        System.out.println(num2);  // 1705032704
        // 精度损失的情况
        int num3 = (int) 3.99F;
        int num4 = (int) 4.11D;
        System.out.println(num3 + "  " + num4);  // 3  4
        // 字符类型与整数类型做数学运算
        char zifu1 = 'A';
        // 计算机底层会用65(二进制)来代表字符A,char类型进行数学运算,按照规则就会翻译成对应的数字
        System.out.println(zifu1 + 1);  // 66
        // 整数类型之间做数学运算
        byte num5 = 40;  // 注意,右侧的数值大小不能超过byte的范围
        byte num6 = 50;
        // byte + byte -->  int + int --> int
        int result1 = num5 + num6;  // 相同变量不能重复使用
        System.out.println(result1);  // 90
        // byte + byte -->  int + int --> byte
        byte result2 = (byte) (num5 + num6);  /* 强制转换:必须保证真实大小本来就没有超过byte范围,否则会发生数据溢出*/
        System.out.println(result2);  // 90
    }
}
算术运算符
运算法:四则运算 和 取模:+ - * / %
对于一个整数的表达式来说,除法用的是整除(python3中用 // 表示整除)
一旦运算中有不同的数据类型,那么结果将会是数据类型范围大的那种
public class DemoPerator{
    public static void main(String[] args){
        // 两个整数常量之间的数学运算
        System.out.println(20 + 30);  // 50
        
        // 两个变量之间的数学运算
        int a = 20, b = 30;
        System.out.println(a + b); // 50
        
        // 变量和常量之间混合使用
        System.out.println(a * 10);  // 200
        
        // 整除和取余
        System.out.println(b / a);  // 1
        System.out.println(b % a);  // 10
        
        // 不同数据类型之间的运算,按范围大的标准来处理
        // int + double --> double + double --> double
        double result = a + 2.5;
        System.out.println(result);  // 22.5
        int result2 = (int) (a + 2.5);
        System.out.println(result2);  // 22  发生了强制转换
    }
}
“+” 的特殊意义:
- 对于数值来说,那就是加法
- 对于 char 类型来说,在计算之前,char 会被提升为 int,然后再计算
- 对于字符串 String 来说,加号表示字符串的连接,任何数据类型和字符串进行连接时,结果都会变成字符串(python中 str + int 会报错)
demo:
public class DemoPlus{
    public static void main(String[] args){
        // 字符串的连接
        String str1 = "Hello";
        System.out.println(str1 + " World!");  // Hello World!
        
        // 字符串和数字类型连接
        System.out.println(str1 + 20);  // Hello20
        // 与多个数字的连接
        System.out.println(str1 + 20 + 30);  // Hello2030
        // 优先级,使用小括号
        System.out.println(str1 + (20 + 30));  // Hello50
    }
}
自增、自减运算符(++、--):
- 在单独使用时,前++ 和 后++没有任何区别
- 在与赋值和打印混合使用时,有很大区别,如果是前++,那么变量立刻+1,然后拿着结果使用,如果是后++,那么先拿变量原来的值,然后+1
- 总结:前++是先加后用,后++是先用后加
demo:
public class DemoOperator{
    public static void main(String[] args){
        // 与打印操作混合使用
        int num1 = 10;
        System.out.println(++num1);  // 11
        System.out.println(num1++);  // 11
        System.out.println(num1);  // 12
        
        // 与赋值语句混合使用
        int num2 = 20;
        int num3 = num2++;
        int num4 = --num2;
        System.out.println(num3);  // 20
        System.out.println(num4);  // 20
        
        // 两个混合使用
        int x = 100;
        int y = 200;
        int result = ++x + y--;
        System.out.println(result);  // 301
        System.out.println(x);  // 101
        System.out.println(y);  // 199
    }
}
赋值运算符
基本赋值运算符:=,将右侧数据交给左侧变量
复合赋值运算符:+= -= *= /= (与python中一样)
public class DemoOperator{
    public static void main(String[] args){
        byte num1 = 10;
        // num1 = num1 + 5
        // num1 = byte + int --> int + int --> int 然后 int --> byte
        num1 += 5;  // 这里发生了一个强制类型转换
    }
}
比较运算符:>=、<=、==、!=
比较运算符的结果一定是一个boolean值,成立就是true,不成立就是false
如果进行多次判断,不能连着写,例如:1< x < 20
public class DemoOperator{
    public static void main(String[] args){
        int num1 = 10;
        System.out.println(num1 == 10);  // true
        System.out.println(num1 != 10);  // false
        
        // 不能进行多次判断
        // System.out.println(1 < num1 < 20);
    }
}
逻辑运算符:&&、||、!
逻辑运算符只能用于boolean值,与、或需要左右各自有一个 boolean 值,但是取反只要有唯一的一个 boolean 值
与、或两种运算符,如果有多个条件,可以连续写,例如:A && B && C
&&、|| 具有短路的效果:如果根据左边已经判断得到结果,那么右边的代码将不再执行,从而节省一定的性能
public class DemoLogic{
    public static void main(String[] args){
        System.out.println(true && true);  // true
        System.out.println(1 < 2 && 2 < 3);  // true
        
        System.out.println(false || true);  // true
        
        // 短路效果
        int num1 = 10;
        System.out.println(false && ++num1 < 10);  // false    ++num1 并不会执行
        System.out.println(num1);  // 10
        System.out.println(true && ++num1 < 10);  // false    ++num1 会执行
        System.out.println(num1);  // 11
    }
}
三元运算符
一元运算符:只需要一个数据就可以操作的运算符,例如:取反!、自增++、自减--
二元运算符:需要两个数据才可以进行操作的运算符,例如:赋值,做加法运算
三元运算符:三个数据进行操作的运算符,在 python 中也叫三元表达式
**格式:数据类型  变量类型  =  条件判断  ?  表达式A : 表达式B;
**
int num = a > b ? a : b; 【a, b 都要符合左侧数据类型的要求】
public class TernaryExpression {
    public static void main(String[] args){
        int a = 10;
        int b = 20;
        int max = a > b ? a : b;
        System.out.println("最大值:" + max);  // 20
        // 错误的写法,必须保证表达式都符合左侧数据类型的要求
        // int min = a < b ? 2.5 : b
    }
}
流程判断
分三种:if、if-else、if-else if-else
public class DemoIfElse{
    public static void main(String[] args){
        int score = 95;
        if (score >= 90 && score <=100) {
            System.out.println("A");
        } else if (score >= 80 && score <90){
            System.out.println("B"); 
        } else if (score >= 70 && score <80){
            System.out.println("C");
        } else if (score >= 60 && score <70){
            System.out.println("D");
        } else if (score >= 0 && score <60){
            System.out.println("flunk!");
        } else {
            System.out.println("illegal data!");
        }
    }
}
switch语句
使用注意事项:
- 多个case后面的数值不可以重复
- switch后面的小括号当中只能是:基本数据类型中的 byte, short, int, char 和 引用数据类型中的 String, enum(枚举)
- switch语句格式可以很灵活:前后顺序可以颠倒,所以 break 语句最好不要省略
demo:
public class DemoSwitch{
    public static void main(String[] args){
        int num1 = 8;
        switch (num1){
            case 1:
                System.out.println("Monday");
                break;
            case 2:
                System.out.println("Tuesday");
                break;
            case 3:
                System.out.println("Wednesday");
                break;
            case 4:
                System.out.println("Thursday");
                break;
            case 5:
                System.out.println("Friday");
                break;
            case 6:
                System.out.println("Saturday");
                break;
            case 7:
                System.out.println("Sunday");
                break;
            default:
                System.out.println("illegal data!");
                break;
        }
    }
}
循环
for 循环
public class DemoForLoop{
    public static void main(String[] args){
        for (int hour = 0; hour < 24; hour++){
            for (int minute = 0; minute < 60; minute++){
                System.out.println(hour + "时" + minute + "分");
            }
        }
    }
}
while 循环
public class DemoWhileLoop{
    public static void main(String[] args){
        int flag = 1;
        while (true){
            System.out.println(flag);
            if (flag == 10){
                break;
            }
            flag += 1;
        }
    }
}
方法
方法的定义:方法名称的命名规则和变量一样,使用小驼峰体
public static void methodName(){
    methodBody;  // 可以为空,不需要写pass占位符
}
注意事项:
- 方法定义的先后顺序没有区别(因为java是先编译后执行)
- 方法的定义不能产生嵌套包含关系
- 方法定义完后,需要调用执行
- 如果方法有返回值,那么必须写"return 返回值",返回值类型必须和方法返回的类型对应起来
定义一个方法:
public class DemoMethod{
    public static void main(String[] args){
        // 程序执行入口,调用方法
        mySelf();
    }
    
    // 定义一个方法
    public static void mySelf(){
        System.out.println("my name is johny");
    }
}
方法传参:
public class DemoMethodArgs{
    public static void main(String[] args){
        int a = 10, b = 20;
        int result1 = sum(a, b);
        int result2 = sum(10, 20);
        System.out.println(result1);
        System.out.println(result2);
    }
    // 定义一个方法
    public static int sum(int a, int b){
        int result = a + b;
        return result;
    }
}
定义一个方法,用来判断两个数字是否相等:
public class DemoMethodSame{
    public static void main(String[] args){
        boolean same = isSame(10, 10);
        System.out.println(same);
    }
    public static boolean isSame(int a, int b){
        // 方式一:if-else
        /*if (a == b){
            return true;
        } else {
            return false;
        }*/
        // 方式二:三元表达式
//        return a == b ? true : false;
        
        // 方式三
        return a == b;
    }
}
方法的重载:定义多个方法的名称一样,但是参数列表不同,好处是,只需记住方法名,就可以实现类似的多个功能,例如 println 方法就是实现的重载
public class DemoOverLoad{
    public static void main(String[] args){
        System.out.println(same((byte) 10, (byte) 10));
        System.out.println(same((short) 10, (short) 20));
    }
    public static boolean same(byte a, byte b){
        return a == b ? true : false;
    }
    public static boolean same(short a, short b){
        return a == b;
    }
}
一个方法可以有0、1、N个参数;那么方法中如果产生了多个返回结果,可以用一个数组进行返回(问题:如果方法中产生了不同类型的返回结果,该如何处理?)
- 任何类型数据都能作为方法的传参,或返回值类型 
- 数组作为方法的参数,传递的是数组的内存地址值,数组作为方法的返回值,返回的也是数组的内存地址值 - public class DemoArrayReturn{ public static void main(String[] args){ int[] arrayResult = calculate(10, 20, 30); System.out.println("sum is:" + arrayResult[0]); // 60 System.out.println("argv is:" + arrayResult[1]); // 20 }  // 定义一个计算的方法 public static int[] calculate(int a, int b, int c){ int sum = a + b + c; int argv = sum / 3; // 静态初始化一个数组 int[] resultArray = {sum, argv}; return resultArray; } } 
数组
- 数组是一种引用数据类型
- 数组中的多个数据的类型必须一致
- 数组长度不可变
- 直接打印数组名称,得到的是数据在内存的 hash 值(十六进制)
创建数组的两种方式:
// 两种创建数组的方式:动态初始化(指定长度),静态初始化(指定内容)
public class DemoArray{
    public static void main(String[] args){
        // 定义一个长度为10,类型为int的数组
        int[] arrayA = new int[10];
        // 定义一个长度为20,类型为字符串的数组
        String[] arrayB = new String[20];
        
        // 静态初始化
        byte one = 1, two = 2, tree = 3, four = 4;
        byte[] arrayC = new byte[] {one, two, tree, four};
        String[] arrayD = new String[] {"hello", "world", "java"};
        
        // 静态初始化省略格式
        byte[] arrayE = {one, two, tree, four};
        String[] arrayF = {"hello", "world", "java"};
    }
}
数组初始化步骤拆分(先定义后赋值):
public class DemoArraySplit{
    public static void main(String[] args){     
        // 静态初始化的拆分
        String[] arrayA;
        // arrayG = {"hello", "world"};    // 这样写不行
        arrayA = new String[] {"hello", "world"};
        
        // 动态初始化的拆分写法
        int[] arrayB;
        arrayB = new int[5];
    }
}
对象数组:
public class Person {
    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 static void main(String[] args) {
        Person one = new Person();
        Person two = new Person();
        Person three = new Person();
        // 创建array(静态省略写法)
        Person[] array = {one, two, three};
        one.setName("甲");
        System.out.println(array[0].name);  // 甲
    }
}
补充:数组必须进行 new 初始化才能使用其中的元素,如果只是赋值了 null,没有进行 new 创建,那么会出现空指针异常:NullPointerException
public class DemoArrayNull{
    public static void main(String[] args){
        int[] arrayA = null;
        // arrayA = new int[3];  // NullPointerException
        System.out.println(arrayA[0]);
    }
}
知识补充:
java的内存需要划分成5个部分
- 栈(Stack):存放的都是方法中的局部变量,方法的运行一定要在栈中运行 - 局部变量:方法的参数,或者是方法内部的变量
- 作用域:一旦超出作用域,立刻从栈内存中消失
 
- 堆(Heap):凡是new出来的东西,都在堆当中 - 堆内存里面的东西都有一个地址值(十六进制),例如直接打印数组名称 
- 堆内存里面的数据,都有默认值,规则如下: 
- 如果是整数, 默认为0 
- 如果是浮点数, 默认为0.0 
- 如果是字符, 默认为 ‘/u0000’ 
- 如果是布尔, 默认为false 
- 如果是引用数据类型, 默认为null 
 
- 方法区(Method Area): - 存储 .class 相关的信息,包含方法的信息
 
- 本地方法栈(Native Method Stack):与操作系统有关 
- **寄存器(PC Register)**:与CPU相关 
ending ~
 
  
  
  
 
 
  
 
 
 