1.当使用实例来访问类成员时,实际上依然是委托给该类来访问类成员变量,因此即使某个实例为null,它依然可以访问它所属的类方法。
public class test9{
private static final int a;
static { //如果不加static 那么他就是普通初始化块,不会给类变量赋值
a = 9;
}
public static void main(String[] args){
test9 one = null;
System.out.println(one.a);
}
}
2.单例类:一个类始终只能创建一个实例。为了限制该类只能创建一个实例,那么就应该把他的构造器使用 private修饰,使他隐藏起来。但是为了能有第一个实例创建,那么就需要一个 public修饰的方法,以备供其他类调用。这个方法还需要用 static修饰。(因为如果不使用public修饰,那么就需要实例去调用这个方法,但是当这个方法运行之前,还没有实例,因此调用这个方法的不可能是对象,只可能是类)。
class singee{
private static singee instance; //声明一个类成员变量来保存该类的实例
private singee(){} //私有的构造函数,限定了其他类不能调用
public static singee getinfo(){ //public声明的方法里添加了构造函数,所以其他类可以通过调用这个方法来构造这个类的实例
if(instance ==null){ //做判断,如果instance为空,那么就创建一个instance实例
return instance = new singee();
}else
{
return instance; //如果不为null,则返回改类实例
}
}//if switch等等函数如果设置了返回方法,每个选择都要加个return。
}
public class single{
public static void main(String[] args){
singee s1 = singee.getinfo();
singee s2 = singee.getinfo();
System.out.println(s1==s2);
}
} //为什么要用static修饰getinfo方法,因为该方法是创建一个实例的,那么调用这个方法的时候,还没有实例生成
3.final修饰符:表示当给一个成员变量赋予初始值后,该成员变量不会再改变。由于在创建对象的时候,如果没有给成员变量设置默认值,那么系统就会默认给成员变量设置默认值。而final修饰的成员变量一旦赋予了初始值,那么这个成员变量就不可再改变,那么这些成员变量就是去了存在的意义。因此规定final修饰的成员变量必须赋予初始值。
类变量:在静态初始化块或者声明该类变量时赋予初始值。
实例变量:在非静态初始化块,构造器或者声明该实例变量时赋予初始值 。
如果打算在构造器或者初始化块中对final修饰的成员变量进行初始化,那么不要在初始化之前就访问成员变量,因为系统不会给final修饰的成员变量默认赋值
public class test11{
final static String name;
final int a;
final String b;
final char c= 97; //直接给一个char型c变量赋值为97;
{
//System.out.println("a的值是"+a) 因为程序不会给a设置默认值,因此这条语句错误
a=6; //在非静态初始化块中给a赋值
System.out.println("a的值是"+a); //a已经被赋值了
}
static{
name = "pennies";
System.out.println("你的名字"+name); //在运行的时候可以看出这第一被打印出来,可以看出是先执行类的初始化,再创建对象
}
public test11(String b){
this.b = b; //在构造器中给b赋值
}
public static void main(String[] args){
test11 aa = new test11("leo");
System.out.println(aa.name);
System.out.println(aa.a);
System.out.println(aa.b);
System.out.println(aa.c);
}
}
3.关于形参赋值:final修饰的形参是不能在方法体中直接赋值的。因为形参是调用该方法时,由系统根据传入的参数来完成初始化。
public class test12{
public int info(final int a){
return a; // 为什么不能在这里给a赋值,因为形参是调用该方法时,由系统根据传入的参数来完成初始化的。
}
public static void main(String[] args){
System.out.println(new test12().info(3)); //这里赋值为3
}}
4.当使用final修饰基本类型变量时,不能对 基本类型变量重新赋值,因此基本类型变量不能被改变。但对于 引用类型变量而言,它保存的仅仅是一个引用,final只保证这个引用类型变量引用的地址不会改变,即一直引用同一个对象,但这个对象可以被改变
class num{
public String a; //如果用final修饰a,那么a就不能被改变
public num(String a){
this.a = a;
}
}
public class test13{
public static void main(String[] args){
final int[] a = {3,4,5,6}; //final修饰一个数组
a[0] = 100;
for( int ex :a){
System.out.println(ex);
}
final num one = new num("33"); //final修饰一个对象
System.out.println("修改前是"+one.a);
one.a = "44"; //将对象的成员变量重新赋值
System.out.println("修改后是"+one.a);
}
}
5.java会使用常量池来管理曾经使用过的字符串直接量,例如执行String a ="LEO";语句之后,常量池中就会缓存一个字符串“LEO”;如果程序再次执行String b = 'LEO';系统就会让b直接指向常量池中的"LEO"字符串,因此a==b将会返回true。
6.final变量宏替换:当final修饰的变量满足以下三点时,这个final变量就可以看作一个直接量
1)使用final修饰;
2)在定义变量时就指定了初始值;
3)该初始值在编译时就被确定了下来。
public class test15{
public static void main(String[] args){
String a ="物品";
String b = "物"+"品";
String c ="物"; //只要将c,d变量设置为final修饰,那么他们就会执行宏替换,那么b就会和c+d指向常量池的同一处
String d = "品";
System.out.println(a==b);
System.out.println(a==(c+d));
}
}
7.final修饰的方法不可被
重写。(还是可以进行重载)
8.final修饰的类不可以有子类。 如(java.lang.Math)
9.不可变类:不可变类是指创建了该类的实例后,该实例的实例变量不可改变。java提供的8个包装类和java.lang.String类都是不可变类。
如果需要创建自定义的不可变类,可以遵循以下规则:
1)使用private和final修饰成员变量;
2)提供带参数的构造器,用于根据传入参数来初始化成员变量;
3)仅为改类提供getter方法,(因为final修饰的变量不可再次被赋值);
4)如果有必要,重写equals()方法和hasecode()方法。
class NAME{
private String firstname; //定义一个String变量,名为firstname;lastname同理
private String lastname;
public NAME(String firstname,String lastname){ //创建类NAME的构造器
this.firstname = firstname;
this.lastname = lastname;
}
public String setFIRSTNAME(String firstname){ //创建放置firstname的方法
return this.firstname = firstname;
}
public String getFIRSTNAME(){ //创建取出lastname的方法
return this.firstname;
}
public String setLASTNAME(String lastname){ //创建放置lastname的方法
return this.lastname = lastname;
}
public String getLASTNAME(){ //创建取出lastname的方法
return this.lastname;
}
}
public class test21{
private final NAME name; //定义一个属于NAME类名为name的成员变量
public test21(NAME name){ //创建一个构造器
this.name = new NAME(name.getFIRSTNAME(),name.getLASTNAME()); //这个构造器调用NAME的构造器,临时创建一个NAME实例来给name赋值
}
public NAME info(){
return new NAME(name.getFIRSTNAME(),name.getLASTNAME());
}
public static void main(String[] args){
NAME N = new NAME("我的","最爱"); //创建一个NAME类的实例N
test21 p = new test21(N); //将N代入类test21的构造器中,将得出来的值赋予实例p
System.out.println(p.info().getFIRSTNAME());
}
}