变量、常量、作用域、关键字、修饰符、标识符、运算符20221222

变量、常量、作用域20241222

变量

◆ 变量是什么:就是可以变化的量!

◆Java是一种强类型语言,每个变量都必须声明其类型

Java变量是程序中最基本的存储单元,其要素包括变量名变量类型作用域

image-20241222154648585

◆ 使用逗号隔开在一行定义多个同类型变量,可以但是不推荐

//int data_04=1,data_05=2,data_06=3;//可以但是不推荐
int data_04=1;
int data_05=2;
int data_06=3;

注意事项:

◆ 每个变量都有类型,类型可以是基本类型,也可以是引用类型

变量名必须是合法的标识符

变量声明是一条完整的语句,因此每一个声明都必须以分号结束

变量作用域

◆类变量

1. 类变量(静态变量,static

  • 定义位置: 类内部,使用 static 关键字修饰。

  • 作用域: 作用域是整个类,可以通过类名直接访问,或者通过实例对象访问。

  • 生命周期: 类变量的生命周期从类加载开始,一直到程序结束。

  • 特点: 类变量属于类本身而不是某个实例,所有实例共享一个类变量。

class Demo {
    static int classVar = 10;  // 类变量
    public static void main(String[] args) {
        System.out.println(Demo.classVar);  // 通过类名访问类变量
    }
}

输出:

10

◆实例变量

2. 实例变量(成员变量)

  • 定义位置: 类内部,但不使用 static 修饰。

  • 作用域: 作用域是整个类,但它必须通过实例化对象来访问。

  • 生命周期:实例变量的生命周期与对象的生命周期一致。当创建对象时,实例变量被分配内存,并且对象被销毁时,实例变量随对象一起销毁。

  • 特点: 每个对象拥有自己独立的实例变量

class Demo {
    int instanceVar = 20;  // 实例变量
    public static void main(String[] args) {
        Demo demo1 = new Demo();
        Demo demo2 = new Demo();
        demo1.instanceVar = 30;  // 修改 demo1 对象的实例变量
        demo2.instanceVar = 40;  // 修改 demo2 对象的实例变量
        System.out.println(demo1.instanceVar);  // 输出 30
        System.out.println(demo2.instanceVar);  // 输出 40
    }
}

输出:

30

40

◆局部变量

3. 局部变量

  • 定义位置: 方法内部代码块(如 ifforwhile 等语句块)内定义的变量。

  • 作用域: 在定义它的方法代码块内有效。其他方法或代码块不能访问该局部变量

  • 生命周期: 局部变量生命周期仅限于方法执行期间一旦方法执行完成,局部变量就会被销毁

  • 特点: 必须在使用前初始化。

/**
 * @Desciption:变量作用域
 * @Author:胖乎乎
 * @Time:2024/12/22
 * */
public class demo04_Variables_Scope {
    //class 类空间   可以定义方法,也可以定义一些属性:变量
    //main 方法    主程序方法
    public static void main(String[] args) {
        //定义局部变量,定在在方法、代码块static{}中的变量
        //生命周期只在两个大括号内,必须声明和初始化值
        int i=10;
        System.out.println("i");
    }
    //其他方法
    public void add(){
    }
}

总结:

1.变量不都要在使用前初始化吗?为什么要强调局部变量在使用前要初始化

是的,你说得对,所有变量在使用前都必须初始化,这一点适用于类变量、实例变量和局部变量。不过,强调局部变量必须在使用前初始化,是因为局部变量有一些特定的行为和规则,这些规则在其他类型的变量中并不完全相同。

(1). 局部变量的初始化要求

在 Java 中,局部变量必须在声明后赋值并初始化才能使用。如果你试图使用一个未初始化的局部变量,编译器会报错。这是 Java 语言的设计决定的,旨在避免因未初始化变量导致的潜在错误。

示例:未初始化的局部变量会报错

public class Demo {
    public void method() {
        int x;  // 局部变量 x 声明但未初始化
        System.out.println(x);  // 错误:变量 x 可能尚未初始化
    }
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.method();//此处调用出错
    }
}

(2). 类变量和实例变量的初始化规则

与此不同,类变量和实例变量的初始化规则有所不同:
  • 类变量(静态变量)如果你没有显式地给类变量赋初值它会自动被赋予默认值。例如,int 类型的类变量会被初始化为 0

  • 实例变量实例变量如果没有显式赋值,Java 会在对象创建时为其分配默认值。例如,int 类型的实例变量会初始化为 0boolean 类型会初始化为 false,引用类型(如 String)会初始化为 null

  • 示例:类变量和实例变量的默认值

public class Demo {
    static int classVar;  // 类变量,默认为 0
    int instanceVar;      // 实例变量,默认为 0

    public static void main(String[] args) {
        Demo demo = new Demo();
        System.out.println(classVar);     // 输出 0
        System.out.println(demo.instanceVar);  // 输出 0
    }
}

输出:

0
0

变量初始化总结:

类变量实例变量可以在声明时不初始化,它们会自动被赋予默认值。

局部变量 必须在声明后被显式必须初始化,否则编译器会抛出错误。

2.类变量可以修改吗?怎么修改

是的,类变量的值是可以修改的。类变量(也叫静态变量)在 Java 中属于类本身,而不是某个具体的实例。你可以通过类名或类的实例来修改类变量的值。

修改类变量的方式:

  1. 通过类名修改类变量的值:
    • 这是推荐的做法,因为类变量属于类本身,不需要创建对象就可以访问和修改它。
  2. 通过类的实例修改类变量的值:
    • 虽然可以通过实例来访问类变量但这种方式并不推荐,因为它可能引起混淆,类变量本身是属于类的最好通过类名来访问。
class Demo {
    // 类变量,使用 static 修饰
    static int classVar = 100;

    public static void main(String[] args) {
        // 通过类名修改类变量的值
        Demo.classVar = 200;

        // 通过类的实例修改类变量的值
        Demo demo = new Demo();
        demo.classVar = 300;

        // 打印类变量的值
        System.out.println("类变量通过类名修改后的值: " + Demo.classVar);  // 输出:300
        System.out.println("类变量通过实例修改后的值: " + demo.classVar); // 输出:300
    }
}

通过类名修改类变量:Demo.classVar = 200;
通过类名直接修改类变量值,这种方式是推荐的,因为它清楚地表明了该变量属于类。

通过实例修改类变量:demo.classVar = 300;
虽然你也可以通过实例 demo 来修改类变量的值,但不推荐这么做。通过实例修改类变量容易让人混淆认为它是实例变量,而实际它是类变量。

3.实例变量可以修改吗?怎么修改

是的,实例变量是可以修改的。实例变量属于对象(实例),每个对象都有自己独立的实例变量值。你可以通过实例化的对象来修改实例变量的值。

修改实例变量的方式:

  1. 通过实例对象修改实例变量的值
    • 实例变量的值通常是在对象被创建时分配的,但你可以通过对象访问并修改它。
  2. 通过方法修改实例变量的值
    • 实例变量可以通过对象的方法(尤其是 setter 方法)来修改,常见于封装(Encapsulation)设计模式。
class Demo {
    // 实例变量,属于对象
    int instanceVar = 10;
    // 方法,用于修改实例变量的值
    public void setInstanceVar(int value) {
        instanceVar = value;
    }
    public static void main(String[] args) {
        // 创建 Demo 对象
        Demo demo = new Demo();
        // 通过对象修改实例变量的值
        demo.instanceVar = 20;
        // 打印实例变量的值
        System.out.println("修改后的实例变量值: " + demo.instanceVar);  // 输出:20
        // 使用方法修改实例变量的值
        demo.setInstanceVar(30);
        // 打印修改后的实例变量的值
        System.out.println("通过方法修改后的实例变量值: " + demo.instanceVar);  // 输出:30
    }
}

Demo.instanceVar 输出是什么还是10吗?

在你提供的代码中,Demo.instanceVar 是不合法的,因为 instanceVar 是一个 实例变量,而不是 类变量。实例变量需要通过 对象 来访问,不能直接通过类名访问。

正确的访问方式:你可以通过 对象 来访问和修改 instanceVar,如 demo.instanceVar,但 不能通过类名 Demo.instanceVar 来访问实例变量,因为它属于对象,而不是类。

我在新建一个对象demo1,他的instanceVar 的值是多少

在你提供的代码中,当你创建一个新的 Demo 对象(如 demo1)时,demo1instanceVar 值将会是 10,这是因为 instanceVar 是实例变量,每个对象都有自己独立的实例变量。

4.变量作用域总结

变量类型 定义位置 作用域 生命周期 初始化要求
类变量 类内,static 修饰 全类,类中所有方法和对象都可以访问 类加载开始,到程序结束 不需要(默认值)
实例变量 类内,static 不修饰 全类,但只能通过对象访问 与对象同生命周期,创建对象时分配内存 不需要(默认值)
局部变量 方法内部,或代码块内 仅限于定义它的方法或代码块 方法执行期间或代码块执行期间 必须初始化

5.变量的优先级

如果类变量、实例变量和局部变量的名字相同,Java 会根据作用域优先级来决定访问哪个变量:

  • 局部变量:优先级最高,局部变量会遮蔽实例变量和类变量。

  • 实例变量:如果没有局部变量,它将被使用。

  • 类变量:最后才会使用类变量。

    class demo04_Variables_Scope {
        // 类变量,属于类
        static int var = 100;
        // 实例变量,属于对象
        int var = 200;
        // 方法,演示变量的作用域
        public void testMethod() {
            // 局部变量,属于方法
            int var = 300;
            // 打印当前方法内的局部变量值
            System.out.println("局部变量 var: " + var);  // 输出:300
            // 在方法内部访问实例变量
            System.out.println("实例变量 var: " + this.var);  // 输出:200
            // 访问类变量(静态变量)
            System.out.println("类变量 var: " + demo04_Variables_Scope.var);  // 输出:100
        }
        public static void main(String[] args) {
            // 创建对象
            demo04_Variables_Scope demo = new demo04_Variables_Scope();
            demo.testMethod();
        }
    }
    

代码理解:

1.类变量
class Test {
    // 类变量,使用 static 修饰
    static int classVar = 100;
    public static void main(String[] args) {
        // 通过类名修改类变量的值
        Test.classVar = 200;
        // 通过类的实例修改类变量的值
        Test test = new Test();
        Test.classVar = 300;
        // 打印类变量的值
        System.out.println("类变量通过类名修改后的值: " + Test.classVar);  // 输出:300
        System.out.println("类变量通过实例修改后的值: " + test.classVar); // 输出:300
        // 创建另一个 Test 对象
        Test test1 = new Test();
        System.out.println("类变量通过实例修改后的值: " + test1.classVar); // 输出:300
    }
}

解释:

  1. 通过类名修改类变量的值

    Test.classVar = 200;
    

    这里通过 Test.classVar 修改了类变量的值,将其设置为 200。但是后面又将类变量的值修改为 300,所以最终的值是 300

  2. 通过实例修改类变量的值

    Test test = new Test();
    Test.classVar = 300;
    

    通过实例 test 修改类变量的值,仍然会影响所有实例的类变量,因为类变量是所有实例共享的。即使你是通过实例来修改类变量的值,其他实例仍然会看到相同的值。

  3. 打印输出

    • 通过类名修改后的值Test.classVar 被修改为 300,因此第一次输出是 300
    • 通过实例修改后的值test.classVar 也是 300,所以第二次输出是 300
    • 另一个实例 test1 的类变量值: 即使是通过 test1 创建了新的对象,test1.classVar 也是 300,因为 classVar 是类变量,所有实例共享同一份数据。
2.实例变量
	**实例变量,属于对象**
class Test {
    // 实例变量,属于对象
    int instanceVar = 10;
    // 方法,用于修改实例变量的值
    public void setInstanceVar(int value) {
        instanceVar = value;
    }
    public static void main(String[] args) {
        // 创建 Test 对象
        Test test = new Test();
        // 通过对象修改实例变量的值
        test.instanceVar = 20;
        // 打印实例变量的值
        System.out.println("修改后的实例变量值: " + test.instanceVar);  // 输出:20
        // 使用方法修改实例变量的值
        test.setInstanceVar(40);
        // 打印修改后的实例变量的值
        System.out.println("通过方法修改后的实例变量值: " + test.instanceVar);  // 输出:40
        // 创建另一个 Test 对象 test2
        Test test2 = new Test();
        // 打印 test2 的实例变量值
        System.out.println(test2.instanceVar);  // 输出:10
    }
}

常量

初始化(initialize)后不能再改变值!不会变动的值。所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变

final 常量类型 常量名=值;

final double PI=3.14;

常量名一般使用大写字符

public class Demo06_Constant {
    //修饰符不区分先后位置  final static double PI=3.14159265358979323846
    static final double PI = 3.14159265358979323846;
    public static void main(String[] args) {
        System.out.println(PI);
    }
}

命名规范

  1. 所有变量、方法、类名:见名知意

  2. 类变量:首字母小写驼峰原则:monthSalary 除了第一个单词以外,后面的单词首字母大写lastname lastName

  3. 局部变量:首字母小写驼峰原则

  4. 常量:大写字母下划线:MAX_VALUE

  5. 类名:首字母大写驼峰原则: Man,GoodMan

  6. 方法名:首字母小写驼峰原则:run(),runRun()

关键字、修饰符、标识符20221222

1. 关键字 (Keyword)

关键字是 Java 语言中具有特殊意义的保留字不能用作变量名、方法名、类名等标识符。它们是 Java 语言的基本组成部分,每个关键字都在编译时具有特定的作用。

常见的关键字:

  • 控制结构if, else, while, for, switch, break, continue, return
  • 数据类型int, boolean, char, double, float, long, byte
  • 访问控制public, private, protected, default
  • 修饰符static, final, abstract, synchronized, volatile
  • 类和对象相关class, interface, extends, implements, new, this, super, instanceof
  • 异常处理try, catch, throw, throws, finally
  • 其他package, import, void, native, enum, assert, instanceof

2. 修饰符 (Modifier)

修饰符是用于修饰类、方法、变量等的关键字,用来控制它们的访问权限、行为、特性等。修饰符可以分为两大类:访问修饰符和非访问修饰符。

访问修饰符:

  • public:表示类、方法或变量对所有其他类可见。
  • private:表示类的成员只对当前类可见。
  • protected:表示类的成员对当前类、同一包中的类以及子类可见。
  • default(包访问权限):没有修饰符时,表示类成员仅对同一包内的类可见。

非访问修饰符:

  • static表示类的成员是类级别的,属于类本身,而不是对象实例。
  • final表示变量是常量,不能修改;方法不能被重写;类不能被继承。
  • abstract表示类是抽象类,不能实例化;方法是抽象方法,必须由子类实现。
  • synchronized:表示方法是线程安全的,确保只有一个线程可以执行该方法。
  • volatile:表示变量的值可能会在不同线程中发生变化,告诉编译器不要对该变量进行优化。
  • transient:表示变量不参与序列化过程。
  • native:表示方法是使用其他语言(通常是 C 或 C++)实现的本地方法。

3. 标识符 (Identifier)

标识符是程序员用来命名类、方法、变量、包、常量等的名称。标识符可以是字母、数字、下划线 (_) 或美元符号 ($),但不能以数字开头。

标识符的规则:

  • 标识符只能包含字母、数字、下划线和美元符号。
  • 标识符不能以数字开头。
  • 标识符不能是 Java 的关键字。
  • 标识符区分大小写(variableVariable 是不同的标识符)。

运算符20241222

运算符参考链接

1.()的优先级最高,因此可以多打一些()提高代码的可读性!!

尽管 Java 中有运算符优先级规则,但不同人对优先级的理解程度不同,某些复杂的运算表达式使用括号会显得更加清晰。例如,对于一个长的算数表达式,括号可以帮助显式地表达计算顺序,避免产生歧义。

int result = 10 + 5 * 3;
int result = 10 + (5 * 3);
if (a > 10 || b < 5 && c == 20) {
    // some code
}
if (a > 10 || (b < 5 && c == 20)) {
    // some code
}

2.分类总览

小tips:Ctrl+D:复制当前行到下面一行

/** 
 * @classification1:算术运算符      +、-、*、/、%(模:取余)、++(自增)、--(自减)
 * @classification2:赋值运算符       =
 * @classification3:关系运算符      >、<、>=、<=、==、!=(不等于)、instanceof
 * @classification4:逻辑运算符      &&(与)、||(或)、!(非)
 * @classification5:位运算符(注意笔试/面试) &(与)、|(或)、^(异或)、~(取反)、>>(右移(重要))、<<(左移(重要))、>>>(了解即可)
 * @classification6:条件运算符  A?B:C   表达式1 ?表达式 2 :表达式 3
 * @classification7:扩展赋值运算符    +=、-=、*=、/=
 * @classification8:字符串连接符    +
*/

2.1算术运算符 +、-、*、/、%(模:取余)、++(自增)、--(自减)

public class Demo1 {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println(a + b);//30
        System.out.println(a - b);//-10
        System.out.println(a * b);//200
        System.out.println(a / b);//10除20=0.5,但a,b均为int型,因此结果为0
        System.out.println(a / (double)b);//将其中一个强制转为double型即可得出正确答案
        System.out.println(b % a);//b对a取余数 0
    }
}

++自增、- - 自减

++a :先自增再做其他运算

a++:先做其他运算再自增

public class Demo1 {
    public static void main(String[] args) {
        int a = 1;
        int b = a++;//b=a=1,a=a+1=2(先赋值后自增)
        int c = ++a;//a=a+1=2+1=3,c=a=3(先自增后赋值)
        System.out.println(a);//输出3
        System.out.println(b);//输出1
        System.out.println(c);//输出3
    }
}
public class Demo03 {
    public static void main(String[] args) {
        int a = 1;
        int b = 1;
        System.out.println(a);//1
        System.out.println(b);//1
        System.out.println(a++>=2);//同样是先比较再自增  //false a=2
        System.out.println(++b>=2);//先自增再比较      //true  b=2
        System.out.println(a);//2
        System.out.println(b);//2
    }
}

2.2赋值运算符 =

//=并不表示等于,等于是==
a = b;//将b的值赋值给a
a == b;//表示a等于b

2.3关系运算符 >、<、>=、<=、==、!=(不等于)、instanceof

注意:关系运算符返回的结果是一个布尔值,ture或false

public class Demo1 {
    public static void main(String[] args) {
       int a = 10;
       int b = 20;
       System.out.println(a>b);//返回false
       System.out.println(a<b);//返回true
       System.out.println(a==b);//返回false
       System.out.println(a!=b);//返回true
    }
}

2.4逻辑运算符 &&(与)、||(或)、!(非)

public class Demo1 {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        System.out.println("a && b:"+(a&&b));//逻辑&&(与):两个变量为真则为真  false
        System.out.println("a || b:"+(a||b));//逻辑||(或):一个变量为真则为真  true
        System.out.println("!b:"+(!b));//逻辑非(!):若为真结果则为假,若为假结果则为真 true
    }
}

注意:短路运算:在&&运算中,若前面的表达式为false,则后面的表达式不会执行

public class Demo1 {
    public static void main(String[] args) {
         int a = 1;
         boolean b = (a>3)&&(a++>3);//a>3为假,短路运算原则:后面的表达式不执行
         System.out.println(b);//输出false
         System.out.println(a);//输出1,a还是为1
    }
}

2.5位运算符(注意笔试/面试) &(与)、|(或)、^(异或)、~(取反)、>>(右移(重要))、<<(左移(重要))、>>>(了解即可)

&、|、^、~

A  =  1100 0110
B  =  0011 1100
--------------------------------------------
A&B = 0000 0100 (与&:两个1则为1,其余为0)
A|B = 1111 1110 (或|:两个0则为0,其余为1)
A^B = 1111 1010 (异或^:两个相同则为0,不同则为1)
~A  = 0011 1001 (取反~:若是1则为0,若是0则为1)

<<、>>:效率极高!!

public class Demo1 {
    public static void main(String[] args) {
        int a = 2;
        int b =(a<<3);//2<<3 = 2*2*2*2(2左移3位)
        System.out.println(b);//输出16
        /*
        2*8=16 //2*2*2*2=16(2的4次方)
        << : *2
        >> : /2
        ----------------------------
        //二进制移位,1向左移动一位等于*2
        0000 0001:1
        0000 0010:2
        0000 0100:4
        0000 1000:8
        0001 0000:16 (2左移3位)
         */
    }
}

2.6条件运算符 A?B:C 表达式1 ?表达式 2 :表达式 3

表达式1 ?表达式 2 :表达式 3

如果表达式1正确则输出表达式2,否则输出表达式3
int c = 10;
int d = 20;
//如果c等于d则e=c,若不等于则e=c+d
int e =(c==d) ? c :c + d;
System.out.println(e);//输出结果为30

2.7扩展条件运算符 +=、-=、*=、/=

例如:a+=b意为a=a+b

int c = 10;
int d = 20;
c += d;//c=c+d
System.out.println(c);//输出30

2.8字符串连接符(面试考题) +

public class Demo1 {
    public static void main(String[] args) {
        //字符串连接符'+':若一方为String类型,则会将另一方转为String类再进行拼接
        int a = 10;
        int b = 20;
        System.out.println(""+a+b);//输出1020
        System.out.println(a+b+"");//输出30,因为String类型在后面,所以前面的a+b会先运算再进行拼接
    }
}

System.out.println(""+a+b);//输出1020
System.out.println(a+b+"");//输出30因为String类型在后面,所以前面的a+b会先运算再进行拼接

数据优先级

public class Demo02 {
    public static void main(String[] args) {
        double data_01=231312.324123;
        float data_02=3.12434532f;
        long data_03=123456789L;
        int data_04=123;
        short data_05=1234;
        char data_06='a';
        byte data_07=127;
        boolean data_08=true;
        /*
        System.out.println((String) (data_01+data_02+data_03+data_04+data_05+data_06+data_07));
        System.out.println((String) (data_02+data_03+data_04+data_05+data_06+data_07));
        System.out.println((String) (data_03+data_04+data_05+data_06+data_07));
        System.out.println((String) (data_04+data_05+data_06+data_07));
        System.out.println((String) (data_05+data_06+data_07));
        System.out.println((String) (data_06+data_07));
        System.out.println((String) data_07);
        */
        System.out.println((data_01+data_02+data_03+data_04+data_05+data_06+data_07));
        System.out.println((data_02+data_03+data_04+data_05+data_06+data_07));
        System.out.println((data_03+data_04+data_05+data_06+data_07));
        System.out.println((data_04+data_05+data_06+data_07));
        System.out.println((data_05+data_06+data_07));
        System.out.println((data_06+data_07));
        System.out.println(data_07);
    }
}

输出结果

1.236896854484683E8
1.23458368E8
123458370
1581
1458
224
127

在 Java 中,字符(char)和字节(byte)在进行算术运算时,会被自动转换为数值型(int),因此 data_06 + data_07 的结果是一个 int

数据类型大小及转换规则

double(64 位、8字节)> float(32 位、4字节)> long(64 位、8字节)> int(32 位、4字节)> char(16位、2字节)>short(16 位、2字节)> byte(8 位、1字节)

posted @ 2024-12-22 21:44  panghuhu~  阅读(117)  评论(0)    收藏  举报