static
凡是由static修饰的东西,都具有两个特点:
1.与对象无关,与类有关;
2.会在类加载期有特殊动作。
static属性
普通属性在内存中是存放在每一个对象身上的。也就是:每new一个对象,在这个对象的存放空间里面就会声明一个普通属性;new多个对象,每个对象的存放空间里面各有一个该属性。所以,我们操作哪个对象,就操作该对象身上的该属性而不会影响其他对象。所以这种属性又叫做成员属性,因为它是组成对象的一部分。
static属性不是存在于每个对象身上的,而是全类共享一个值。该属性是在类加载期就把这个属性产生并放在内存中的静态区。之后无论在代码里面使用对象还是类名区访问该属性,都是指到同一个空间。
static方法
普通方法:与对象相关,体现在:
1.该方法的调用必须用对象.方法的方式
2.该方法的实现部分,能够操作到该对象的普通属性和普通方法
static静态方法:与对象无关,体现在:
1.该方法的调用,可以使用 类名.方法名 调用 且 与对象.方法名 调用没有差异
2.该方法的实现部分只能调用该对象的静态属性和静态方法
两种方法的差异:
1.从场景上看,既然这个方法是静态的,也就是说他的执行与对象无关,那么在它内部也就不应该知道到底在操作哪个对象,也就不能确定这个对象相关的属性和方法。
2.从底层实现看,静态方法在加载期是被优先加载的,也就是说在加载静态方法的时候,还没有加载这个类里面的非静态内容,而如果这个时候静态方法里面调用了非静态内容,JVM会不认识,所以会编译报错。
在我们实际写代码的时候,只有工具类的工具方法才能写成static
或者说无论由哪个对象去执行 效果都是一样的 且不会对该对象造成任何影响,所以这个时候这些对象就只是一个工具,该方法就只是一个工具方法
JDK高版本的新语法
JDK版本从95年的1.0到现在已经发展到18了,但不是所有JDK版本都是LTS版本(LongTimeService版本)
这些LTS版本才是我们可以用在生产环境当中,也是大家需要下载使用的。其他版本很多是测试功能,不能保证稳定性
目前的LTS版本:JDK8(目前使用量最大) JDK11 JDK17
Java中最重要的Spring框架已经宣布在它将要推出的最新版Spring6中不再支持JDK8
从19年开始的面试题中,新技术新语法考察次数增多。
var关键字
JDK10当中提出。用来声明局部变量的,var是JS的一个关键字,Java本身是没有的。
JS是一门弱类型的编程语言
var i = 20; i = "hello";
Java是强类型的编程语言
int i = 20; String s = "hello";
弱类型的语法写起来会更简单,但一旦代码的规模增加,容易出错。强类型语言虽然规范更严格,却更容易构建大型程序
Java引入了var关键字来声明变量,但和JS的var不同
/* 要求:知道即可,面试中能答上来 1.Java中的var只能用来声明局部变量 2.Java中var声明的变量,在第一次赋值以后,就知道自己是什么类型的变量来,后面就不能改了 3.var声明了变量以后,必须在同一条语句马上赋值,不然JVM没办法通过值的类型进行类型推断,也就没有给这个变量分配空间。 4.var在实际使用过程中不太受欢迎,因为没有提供太大的好处,只是在面试中可能会被问到 (老师个人体会:当类型的名字非常长的时候才会想用到它 XMLApplicationContext context = new XMLApplicationContext(); 等价于var context = new XMLApplicationContext(); ) */ var a = "hello"; a = "hello"; //a = 10086; 报错 a变量在第一次赋值后,就确定自己是String类型了,不能改了 var i = 10; var x = new Student(); //这样写也是错的 var test; test =10;
String的文本块
String在内容操作的时候,文本格式化操作很麻烦,比如需要在内部使用\n\t等字符来操作。
在JDK15中,提供了String的文本块功能呢。它的语法如下:
String str = """ 请选择你要执行的操作: 1.查询余额 2.存款 3.取款 4.退出 """; /* 1.没有改变这个str是一个String类型的事实 2.三个开始引号和三个结束引号不能在同一行,字符串内容也要单独成行 */
switch作为表达式返回一个值
JDK12中,增加了yield关键字,可以直接
yield关键字:起到两个作用:1.像break一样的跳出case分支;2.同时把yield后面的值返回出来交给变量
注意:每个返回的类型必须兼容,在每个yield之前可以书写任意代码的
int num = new Scanner(System.in).nextInt(); char c = 0; switch(num){ case 1: c = 'A'; break; case 2: c = 'B'; break; case 3: c = 'C'; break; case 4: c = 'D'; break; default: c = 'E'; break; } /* yield关键字起到两个作用: 1、像break一样跳出case分支; 2、同时,把yield后面的值返回出来交给前面的c变量 注意: 1、每个yield返回的类型必须兼容。 2、在每个yield之前可以书写任意代码的; */ char c = switch (num){ case 1: /* 可以添加处理语句 */ yield 'A'; case 2: yield 'B'; case 3: yield 'C'; case 4: yield 'D'; default: yield 'E'; }; /* 这是一种更特殊的语法, 用->替换yield,返回值。 注意:这种情况每个分支只能返回一个值,不能有其它的处理语句。 */ char c = switch (num){ case 1 -> 'A'; case 2 -> 'B'; case 3 -> 'C'; case 4 -> 'D'; default -> 'E'; };