java学习笔记day02
三、运算
参数传递
java 的参数是以值传递的形式传入方法中,而不是引用传递。
以下代码中Dog dog 的 dog 是一个指针,存储的是对象的地址。在将一个参数传入一个方法时,本质上是将对象的地址以值的方式传递到形参中。
public class Dog { String name; Dog(String name) { this.name = name; } String getName() { return this.name; } void setName(String name) { this.name = name; } String getObjectAddress() { return super.toString(); } }
在方法中改变对象的字段值会改变原对象该字段值,因为引用的是同一个对象。
class Pass ByValueExample { public static void main(String[] args) { Dog dog = new Dog("A"); func(dog); System.out.println(dog.getName()); } private static void func(Dog dog) { dog.setName("B"); } }
但是在方法中将指针引用了其他对象,那么此时方法里和方法外的两个指针指向了不同的对象,在一个指针改变其所指向对象的内容对另一个指针所指向的对象没有影响。
public class PassByValueExample { public static void main(String[] args) { Dog dog = new Dog("A"); System.out.println(dog.getObjectAddress()); // Dog@4554617c func(dog); System.out.println(dog.getObjectAddress()); // Dog@4554617c System.out.println(dog.getName()); // A } private static void func(Dog dog) { System.out.println(dog.getObjectAddress()); // Dog@4554617c dog = new Dog("B"); System.out.println(dog.getObjectAddress()); // Dog@74a14482 System.out.println(dog.getName()); // B } }
float 与 double
java不能隐式执行向下转型,因为这会使得精度降低。
1.1 字面量属于 double 类型, 不能直接将 1.1 直接赋值给 float 变量,因为这是向下转型。
// float f = 1.1;
1.1f 字面量才是 float 类型。
float f = 1.1f;
隐式类型转换
因为字面量 1 是 int 类型,它比 short 类型精度要高,因此不能隐式地将 int 类型向下转型为 short 类型。
short s1 = 1; // s1 = s1 + 1;
但是使用 += 或者 ++ 运算符会执行隐式类型转换。
s1 += 1;
s1++;
上面的语句相当于将 s1 + 1 的计算结果进行了向下转型:
s1 = (short) (s1 + 1); switch
从 Java7 开始,可以在 switch 条件判断语句中使用 String 对象。
String s = "a"; switch (s) { case "a": System.out.println("aaa"); break; case "b": System.out.println("bbb"); break; }
switch 不支持 long、float、double,是因为 switch 的设计初衷是对那些只有少数几个值的类型进行等值判断,如果值过于复杂,那么还是用 if 比较合适。
// long x = 111; // switch (x) { // Incompatible types. Found: 'long',required: //'char,byte,short,int,Charater,Byte,Short,Integer,String,or an enum' // case 111: // System.out.println(111); // break; // case 222: // System.out.println(222); // break; //}
四、关键字
final
1.数据
声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能改变的常量。
对于基本类型,final 使数值不变;
对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身时可以修改的 。
final int x = 1; //x = 2; // cannot assign value to final variable 'x' final A y = new A(); y.a = 1;
2.方法
声明方法不能被子类重写。
private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。
3.类
声明类不允许被继承。
static
1.静态变量
静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。
实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。
public class A { private int x; //实例变量 private static int y; //静态变量 public static void main(String[] args) { //int x = A.x; // Non-static field 'x' cannot be referenced from a static context A a = new A(); int x = a.x; int y = A.y; } }
2.静态方法
静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。
public abstract class A { public static void func1() { } //public abstract static void func2(); //Illegal combination of modifiers: "abstract' and 'static' }
只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字,因为这两个关键字与具体对象关联。
public class A { private static int x; private int y; public static void func1() { int a = x; // int b = y; // Non-static field 'y' cannot be referenced from a static context // int b = this.y; // 'A.this' cannot be referenced from a static context } }
3.静态语句块
静态语句块在类初始化时运行一次。
public class A { static { System.out.println("123"); } public static void main(String[] args) { A a1 = new A(); A a2 = new A(); } }
123
4.静态内部类
非静态内部类依赖于外部类的实例,也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。而静态内部类不需要。
public class OuterClass { class InnerClass { } static class StaticInnerClass { } public static void main(String[] args) { // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot b ereferenced from a static context OuterClass outerClass = new OuterClass(); InnerClass innerClass = outerClass.new InnerClass(); StaticInnerClass staticInnerClass = new StaticInnerClass(); } }
静态内部类不能访问外部类的非静态的变量和方法。
5.静态导包
在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。
import static com.xxx.ClassName.*;
6.初始化顺序
静态变量和静态语句优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。
public static String staticField = "静态变量"; static { System.out.println("静态语句块"); } public String field = "实例变量"; { System.out.println("普通语句块"); }
最后才是构造函数的初始化。
public InitialOrderTest() { System.out.println("构造函数"); }
存在继承的情况下,初始化顺序为:
父类 (静态变量、静态语句块)
子类 (静态变量、静态语句块)
父类 (实例变量、普通语句块)
父类 (构造函数)
子类 (实例变量、普通语句块)
子类 (构造函数)
————————————————
版权声明:本文为CSDN博主「yqqbz」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52120338/article/details/123951114
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!