📕属性
我习惯称它为全局变量,为什么说它是全局变量?
因为不管变量的 访问修饰符 是什么,类的方法体、构造器、代码块和内部类都可以通过 this
对其进行访问,除非它们被 static
修饰。
称它为全局变量又不准确,因为它被 final
修饰时,本质上是不可以改变的。
我为什么说被 final
修饰时本质上不可以改变?因为当全局变量为引用类型时,使用 final
修饰还是可以被改变的,例如下面这段代码:
class A{
final int[] i = {1, 2};
public void visit(){
this.i[0] = 32; // 修改被 final 修饰的
}
}
class Text{
public static void main(String[] args) {
A o = new A();
o.visit();
System.out.println(o.f[0]);
}
}
建议
- 被
static
修饰的属性- 建议设置默认值
- 建议不要与
private
搭配
public static int i = 0;
- 被
final
修饰的属性- 建议不要改动
- 建议不要改动
📕方法
三种方法以及需要遵守的规范:
- 被
abstract
修饰的抽象方法- 不准与
final
搭配 - 不准与
static
搭配 - 不准使用
{}
abstract class A{ protected abstract void visit(){}; }
- 不准与
- 被
static
修饰的静态方法- 不准与
abstract
搭配 - 建议不要与
private
搭配
class A{ public static void visit(){}; }
- 不准与
- 不被前两个修饰的普通方法
部分细节请看 OOP与AOP 关于成员方法的描述。
📕构造器
构造器根据参数分为无参和有参;
根据访问修饰符分为私有和公共;
-
无参构造器
当你在类里面没有定义构造器的时候,默认会生成一个无参构造器。
默认的无参构造器如果没有声明会被有参构造器覆盖。 -
有参构造器
可以传参数实现对象的初始化设置 -
私有构造器
可以实现【单例模式】,从而保证类只有一个实例 -
公共构造器
可以被用于创建多个实例或提供一个模板 -
构造器只能被访问修饰符修饰
构造器在哪些情况下会被执行?
- 对象实例化时
new
强引用 - Java反射机制
newInstance
弱引用
详情请看 OOP与AOP关于构造器的描述。
📕代码块
- 只有
static
可以修饰代码块
因此根据 static
分为:
- 静态代码块
每次 类加载 的时候被执行 - 普通代码块
每次 实例化对象 的时候被执行
💡静态代码块
那么哪些情况下会发生类加载❓
- 实例化对象
new
- 调用类的静态方法
- 使用类的静态属性
只要类的元信息加载到方法区的常量池,就算一次类加载从而执行静态代码块。为了说明这种特性下面给出一个案例观察其有趣的执行方式:
class A{
public static int count = 0;// 静态属性
static {// 静态代码块
++A.count;
System.out.println("第 "+A.count+" 次加载的静态代码块");
}
static void visit(){};// 静态方法
}
class Text{
public static void main(String[] args) {
new A();
new A();
// A.visit();
// System.out.println(A.count);
}
}
结论:当你实例化对象、调用类的静态方法或使用类的静态属性,那么就会执行类的静态代码块但之后再用这种方式(继续实例化对象、调用类的静态方法或使用类的静态属性)将无法执行静态代码块。
💡普通代码块
普通代码块与静态代码块不同,它在每次对象实例化时被执行。可以利用下面的代码来验证:
class A{
public static int count = 0;
static void visit(){};
{
++A.count;
System.out.println("第 "+A.count+" 次加载的普通代码块");
}
}
class Text{
public static void main(String[] args) {
new A();
new A();
// A.visit();
// System.out.println(A.count);
}
}
📕内部类
- 内部类可以在类的方法体里面定义
在方法体里面定义类,可以不用写类的名字。在方法体定义的类,不能使用访问修饰符,可以使用 final 和 abstract 修饰。interface A{ public void visit(); } class B{ public void visit(){ A a = new A(){// 匿名类 public void visit(){System.out.println("a 匿名类的 visit 方法被执行");}; }; a.visit(); } } class Text { public static void main(String[] args) { B b = new B(); b.visit(); } }
只要不是在方法体里面定义的,其修饰的类型比类的方法多,甚至可以在非抽象类里面使用 abstract
和 interface
修饰。
用 static
修饰的内部类,可以在类的外部直接创建,请看下面的案例:
class A {
static class B{// 静态内部类
public void visit(){System.out.println("11111");}
}
}
class Text {
public static void main(String[] args) {
A.B b = new A.B();
b.visit();
}
}
那么内部类如何访问类的属性❓
可以通过class.this.property
进行访问除了 static
修饰的内部类。
class A {
int i = 0;
class B{// 非静态内部类
public void visit(){System.out.println(A.this.i);}
}
}
class Text {
public static void main(String[] args) {
A a = new A();
A.B b = a.new B();
b.visit();
}
}
如果你是无意刷到这篇文章并看到这里,希望你给我的文章来一个赞赞👍👍。如果你不同意其中的内容或有什么问题都可以在下方评论区留下你的想法或疑惑,谢谢你的支持!!😀😀