发布日期:2023-03-31来源:武汉北大青鸟武汉校区作者:武汉宏鹏
java学习笔记05-武汉北大青鸟学子java培训笔记。
一、static修饰符
1. 可以修饰属性、方法、初始代码块,成为类变量、静态方法、静态初始化代码块。
注:初始代码块是在类中而不再任何方法之内的代码块。
2. 类变量、静态方法、静态初始化代码块与具体的某个对象无关,只与类相关,是类公有的。在类加载时初始化。
3. 类加载:虚拟机通过CLASSPATH从磁盘上找到字节码文件,并将字节吗文件中的内容通过I/O流读到内存的过程。在虚拟机的生命周期中一个类只被加载一次。
注:Java命令的作用是启动JVM。
4. Static定义的时一块为整个类共有的一块存储区域,其发生变化时访问到的数据都是经过变化的。
5. 为什么主方法必须是静态的?
主方法是整个应用程序的入口,JVM只能通过类名去调用主方法。
6. 类变量和静态方法可以在没有对象的情况下用:类名.方法名(或属性名)来访问。
7. 静态方法不可被覆盖(允许在子类中定义同名的静态方法,但是没有多态);父类如果是静态方法,子类不能覆盖为非静态方法。父类如果是非静态方法,子类不能覆盖为静态方法。
争论:静态方法可以覆盖但是没有多态。
思考:没有多态的覆盖叫覆盖吗?
在静态方法中不允许调用本类中的非静态成员。
8. 静态初始化代码块只在类加载的时候运行一次,以再也不执行了。所以静态代码快一般被用来初始化静态成员。
9. 不加static为动态初始化代码块,在创建对象时被调用(再构造函数之前)。
二、 什么时候类加载
次需要使用类信息时加载。
类加载的原则:延迟加载,能不加载就不加载。
触发类加载的几种情况:
(1)、调用静态方法时会加载静态方法真正所在的类。
例:通过子类调用父类的静态方法时,只会加载父类而不会加载子类。
(2)、调用静态初始化代码块时要加载类。
(3)、加载子类时必定会先加载父类。
(4)、构造对象的时候会加载。
(5)、调用静态属性时会加载类。
注:如果静态属性有final修饰时,则不会加载。
例:public static final int a =123;
但是如果上面的等式右值改成表达式(且该表达式在编译时不能确定其值)时则会加载类。
例:public static final int a = math.PI
三、final修饰符
1. final可以用来修饰类、属性和方法。
2. final修饰一个属性时,该属性成为常量。
(1)对于再构造方法中利用final进行赋值时候,此时在构造之前系统设置的默认值相对于构造方法失效。
(2)对于实例常量的赋值有两次机会
在初始化的时候通过声明赋值
在构造的时候(构造方法里)赋值
注:不能在声明时赋值一次,在构造时再赋值一次。
注意:当final修饰实例变量时,实例变量不会自动初始化为0;
3. Final修饰方法时,该方法成为一个不可覆盖的方法。
如果一个方法前有修饰词private或static,则系统会自动在前面加上final。即private和static方法默认均为final方法。
4. Final常常和static、public配合来修饰一个实例变量,表示为一个 类公有的公开静态常量。
例:pubic static final int a = 33;
在这种情况下属性虽然公开了,但由于是一个静态常量所以并不算破坏类的封装。
5. Final修饰类时,此类不可被继承,即final类没有子类。
一个final类中的所有方法默认是final方法。
Fianl不能修饰构造方法,构造方法不能被继承更谈不上被子类方法覆盖。
四、 关于final的设计模式:不变模式
1、不变模式:一个对象一旦产生就不可能再修改(string就是典型的不变模式);
通过不变模式可以做到对象共享;
2、池化思想:用一个存储区域来存放一些公用资源以减少存储空间的开销。
例:在String类中有个串池(在代码区)。
(1) 如果用Stirng str = “abc”来创建一个对象时,则系统会先在串池中寻找有没有“abc”这个字符串。如果有则直接将对象指向串池中对应的地址,如果没有则在串池中创建一个“abc”字符串。
所以:String str1 = “abc”;
String str2 = “abc”;
Str1 = = str2 返回值是ture;他们的地址是一样的。也就是说str1和str2都指向了代码空间中相同的一个地址,而这个地址空间保存就是是字符串”abc”;
(2) 如果用String str = new String(“abc”)则直接在堆空间开辟一块存储空间用来存放”abc”这个字符串。
所以:String str1 = new String(“abc”);
String str2 = new String(“abc”);
Str1 = = str2 返回值是false;他们的地址是不一样的。也就是说str1和str2分别指向了堆空间中不同的两个地址,而这两个地址空间保存的都是字符串”abc”;
4、 java.lang下的StringBuffer类。
对于字符串连接
String str=”1”+”2”+”3”+”4”;
产生:
12
123
1234
会在串池中产生多余对象,而真正我们需要的只有后一个对象,用这种方式进行字符串连接时,不管在时间上还是在空间上都会造成相当大的浪费。所以我们应该使用 StringBuffer(线程安的) 或者 StringBuilder(线程不安的)
解决方案:
String s;
StringBuffer sb = new StringBuffer(“1”);
Sb.append(“2”);
Sb.append(“3”);
Sb.append(“4”);
S = sb.toString();
解决后的方案比解决前在运行的时间上相差2个数量级。
五、abstract修饰符
1. 可用来修饰类、方法
2. abstract修饰类时,则该类成为一个抽象类。抽象类不可生成对象(但可以有构造方法),必须被继承使用。
抽象类可以声明,作为编译时类型,但不能作为运行时类型。
Abstract永远不会和private,static,final同时出现。
3. Abstract修饰方法时,则该方法成为一个抽象方法,抽象方法没有实现只有定义,由子类覆盖后实现。
比较:private void print(){};表示方法的空实现
abstract void print();表示方法为抽象方法,没有实现
4. 抽象方法从某中意义上来说是制定了一个标准,父类并不实现,留给子类去实现。
注:抽象类中不一定要有抽象方法,但有抽象方法的类一定是抽象类。
六、 关于抽象类的设计模式:模板方法
灵活性和不变性
在下面这个例子种父类(抽象类)指定了一个标准,而子类根据自己的需求做出不同的实现。
例:/****************************************************/
public class TestTemplateMethod{
public static void main(String[] args){
XiaoPin x1 = new ShuoShi();
XiaoPin x2 = new DaPuKe();
x1.act();
x2.act();
}
}
abstract class XiaoPin{
abstract void jiaoliu();
abstract void xushi();
abstract void gaoxiao();
abstract void shanqing();
public final void act(){
jiaoliu();
xushi();
gaoxiao();
shanqing();
}
}
class ShuoShi extends XiaoPin{
void jiaoliu(){
System.out.println("顺口溜");
}
void xushi(){
System.out.println("写书");
}
void gaoxiao(){
System.out.println("打招呼");
}
void shanqing(){
System.out.println("二人传");
}
}
class DaPuKe extends XiaoPin{
void jiaoliu(){
System.out.println("大家好");
}
void xushi(){
System.out.println("老同学见面");
}
void gaoxiao(){
System.out.println("打扑克");
}
void shanqing(){
System.out.println("马家军");
}
}
/*******************************************************/
Copyright (c) 2006-2023 武汉宏鹏教育咨询有限公司 版权所有 All Rights Reserved.