学习笔记之JavaSE(2)--Java基础语法1

一、Java主类结构

Java主类包括包声明、导入类库、成员变量和局部变量、方法等等,主类存在如下规范

  • 每个Java文件有且只有一个与文件名同名的public主类
  • 除了主类,可以自由定义任意个内部类与普通类(只能是包访问权限)
  • main()方法可以定义在某个Java文件的任意类中(如果在内部类中就必须是静态内部类),可以在不同类中有多个main()方法
  • 每个Java文件最好只有一个类,即为主类,这样便于程序维护

二、关键字与标识符

标识符可以简单地理解为一个名字,用来标识类、方法和变量等等。而关键字就是Java语言中已经被赋予特定意义的一些单词,比如public、int、static等等。

标识符的编写规范:

  • 必须以字母、下划线(_)或者$符号开头,后面可以使用字母、下划线、$符号和数字
  • 不能将关键字作为标识符使用
  • 如果标识符由多个单词组成,使用“驼峰风格”书写,类名首字母大写
  • 区分大小写,同类型的标识符不能重复
  • 选择有意义的单词作为标识符,加强程序可读性

三、变量与常量

Java的数据类型分为基本数据类型引用类型,今天先说一下基本数据类型。
Java的基本数据类型包括:
  1. 整数类型:byte(8位)、short(16位)、int(32位)、long(64位)
  2. 浮点类型:float(32位)、double(64位)
  3. 字符类型:char(16位) 注:1字节为8位,Java使用Unicode编码,中英文字符都是2字节
  4. 布尔类型:boolean

在实际开发中,这八种基本数据类型都有其特定的使用环境:

  • 表示整数首先要考虑的就是int
  • 表示小数一定使用double
  • 表示日期时间数字、文件和内存大小使用long
  • 进行编码转换、数据IO使用byte
  • 处理中文使用char
  • 处理逻辑使用boolean
  • float和short几乎不会使用
需要注意的是,编译器默认将整数字面量视作int类型,将小数字面量视作double类型。在给float类型的变量赋值时,必须在小数后面加f,否则会因为赋值关系错误而使得编译器报错;给long类型赋值时,如果超过了int类型的范围,需要在数值后面加l或L。给Long类型对象初始化时,数值后面必须加l或L,诸如使用equals()等方法时也必须加l或L,比如Long userId = 1L;System.out.println(userId.equals(1L)); 。实际开发中,无论是给long类型变量还是给Long类型对象进行初始化时,最好都要加L

Java基本数据类型的赋值关系:按照byte、short、int、long、float、double的顺序,靠前的可以赋值给靠后的,这就是隐式类型转换。如果靠后的想赋值给靠前的,或者将超出该类型范围的数值赋值给该类型的变量,就需要进行强制类型转换强转的原理就是将多出来的位“削掉! 比如将int型变量赋给byte型,byte只有8位,而int有32位,所以需要进行强转将高24位“削掉”;再比如给byte变量赋值128,128会被编译器视作int类型(这里必须注意!!),且其第9位为1,编译器判断如果进行强制类型转换会丢失精度,所以不通过编译,让我们自己决定是否进行强转
public class Test01 {

	public static void main(String[] args){
		byte b = 1;
		short s = 2;
		int i1 = (int)3.1;//将小数强制类型转换之后赋给整数,会将小数部分截掉
		int i2 = 0;
		long l = 4;
		float f = 0.1f;//给float变量赋值时必须加上f,否则会被当做double值,出现错误
		double d = 0.2;
		char c = 'a';
		//!b = c;char类型的变量不能赋给byte类型的变量
		//!s = c;char类型的变量不能赋给short类型的变量
		i2 = c;//char类型的变量可以赋给int类型的变量
		l = c;//char类型的变量可以赋给long类型的变量
		f = c;//char类型的变量可以赋给float类型的变量
		d = c;//char类型的变量可以赋给double类型的变量
		//!byte b1=128;
		byte b1 = (byte)128;
		//!byte b2 = i1;
		byte b2 = (byte)i1;
		System.out.println("将小数强制类型转换之后赋给整数类型,结果为i="+i1);//结果为3
		System.out.println("字符常量'a'赋值给int,long,float,double变量的结果为"+i2+" "+l+" "+f+" "+d);//结果为97 97 97.0 97.0
		System.out.println("使用强制类型转换给byte变量赋值128之后的结果:b1="+b1);//结果为-128
		System.out.println("使用强制类型转换将int变量赋给byte变量的结果:b2="+b2);//结果为3
	}
}
说到现在有一个疑问,刚才不是说整数的默认类型是int吗?那么给byte型变量赋值1的时候,难道不需要我们进行强转吗?答案是使用常量赋值时,编译器会自动判断强转会不会丢失数据精度!如果判断不会丢失精度,编译器自动帮我们完成强转 ,所以给byte变量赋值常量1可以通过编译;如果判断会丢失精度,编译器就不会帮我们完成强转,而是让我们自己决定是不是使用强转,所以给byte变量赋值常量128的时候,编译器判断强转会丢失精度(因为第9位为1),所以不会通过编译。 但是!!由于等号右边的运算结果一定是默认的int类型,如果我们使用变量赋值的话,编译器就无法判断强转会不会丢失精度,进而无法通过编译(面试重点)!
public class Test02 {
    public static void main(String[] args) {
        byte b = 1 + 2;//由于编译器确定1+2一定在byte的范围内,所以自动进行了强制类型转换,可以通过编译
        byte b1 = 1;
        //!b = b1 + 1;b1+1的结果是int,由于b1是变量,编译器无法判断b1+1是否在byte范围内,所以不能通过编译
        byte b2 = 2;
        //!b = b1 + b2;b1 + b2的结果是int,由于b1, b2都是是变量,编译器无法判断b1 + b2是否在byte范围内,所以不能通过编译
        final byte b3 = 1;
        b = b3 + 1;//虽然b3+1的结果也是int,但是由于b3是常量,所以编译器确定b3+1一定在byte的范围内,所以自动进行了强制类型转换,可以通过编译
    }
}

从代码我们可以看出:虽然1+2是int值,但是1+2的结果是常量,编译器可以确定1+2肯定在byte的范围内,所以可以通过编译,并由编译器完成自动强制类型转换(“削掉”高24位)。但是后面两种情况,b1,b2都是变量,编译器不能确定运算结果是否会超出范围(万一b1改为127呢?“削掉”前三个字节就会造成丢失精度),所以不能通过编译,它的意思就是:你自己决定是不是要强转!注意第三种情况,编译器会将字面量与final变量统一视作常量!!所以编译器可以确定b3+1肯定在byte的范围内,所以可以通过编译,并由编译器自动完成强转。

char和short也存在这种问题。但是int和long不会出现这种问题,因为无论如何等号右边的运算结果都默认为int。如果用变量给int类型变量赋值,编译会通过,但如果运算结果超出了int类型的范围,底层会自动完成强制类型转换(后果是溢出,所以实际上这是一个缺陷。而由于运算结果是int,赋值给long符合隐式类型转换,更加没有问题~


最后说下变量的作用域、生命周期和常量的声明。

  • 变量分为成员变量(类中声明的变量)与局部变量(方法体中声明的变量),成员变量又分为实例变量与静态变量
  • 成员变量可以不初始化,局部变量必须初始化(这是由不同内存区域的特性决定的,后面会说)
  • 例外:final成员变量也必须初始化
  • 实例变量的作用域是整个类;静态变量的作用域是整个应用程序;而局部变量的作用域是从定义它的最近的‘{’符号到对应的‘}’符号
  • 静态变量存在于方法区,JVM进程结束才会被销毁;实例变量存在于堆中的对象里,除非对象被回收,否则不会被销毁;而局部变量存在于虚拟机栈的帧栈,一旦定义该局部变量的方法结束调用,帧栈弹出,局部变量就会被销毁
  • 局部变量可以与成员变量的名字相同,在其作用域内成员变量被覆盖
  • Java不能在局部代码块中重复定义同名局部变量(局部代码块的作用是控制局部变量的作用域,不常用
  • 常量声明使用static和final关键字,常量名最好大写,final代表该值不能被改变,至于为什么要用static等学到静态再做总结

public class Test03 {
    private int i1;//实例变量声明,可以不初始化,但是JVM会给变量默认初始化为0
    private static int i2;//静态变量声明,可以不初始化,但是JVM会给变量默认初始化为0

    public static void main(String[] args) {
        Test03 t = new Test03();
        t.test();
        System.out.println("方法调用结束后,i1的值为" + t.i1 + ",证明方法调用结束后,局部变量被销毁了");//不管是不是在本类中,要在静态方法里面调用实例变量,必须使用引用.变量的格式
        System.out.println("i2 = " + i2);//在本类中,静态变量的可以直接在静态和非静态方法调用,之所以能直接调用静态变量,是编译器自动在i2前加了类名Test03.
        System.out.println("Test类的final静态变量COUNT = " + Test.COUNT);//在不同类中,要使用类名.变量的格式调用静态变量
    }

    public void test() {
        System.out.println("在非静态方法中,i1的值为" + i1);//在本类中,非静态变量的可以直接在非静态方法调用,之所以能直接调用实例变量,是编译器自动在i1前加了this.
        int i1 = 1;//局部变量必须初始化
        System.out.println("定义局部变量i1后,i1的值为" + i1 + ",很明显,局部变量覆盖了成员变量");
        {
            //!int i1 = 2;不能在局部代码块中重复定义同名局部变量
        }
    }
}

class Test{
    static final int COUNT = 3;//final静态变量(也可以视作常量)的声明与指定初始化 (final变量必须初始化)
}


其中有关于静态变量与静态方法的知识后面再说,静态很重要!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值