面向对象
07.08
理解访问修饰符 (信息隐藏)
被访问被调用的范围
- public :全部
- 默认 :同包
- protected :同包或有继承关系的类
- private :只有同类
在A类中定义属性和方法:
- public:这个类的实例化对象可以访问;
- 默认: 如果在同包下定义一个主类,然后在主类的主方法里面new A的一个对象出来,则这个对象可以访问被默认修饰的属性和方法;
- protected:在同一个包下的类中new的A类对象和继承了A类的相同或不同包下的子类中new A类对象,这个对象能调用A类中所有的属性和方法(不同包下没有继承关系的类不能访问)
- private:只有这个类中的属性和成员方法能访问
geter和setter更深入理解
- 当把类的属性和方法访问权限设置为private时,一般都提供上面2个公共方法;
在这2个方法体内,可以添加一些限制代码;
比如说setter方法,需要用户输入账号密码才有权限修改
getter也可以这么做,还可以在返回值的时候做一些动作;
这就是隐藏. - 也可以用private修饰setter方法,那么这个属性就是只读;
- 用private修饰getter方法,这个属性就是只写;
封装的好处
- 类的成员变量可以成为只读或只写
- 类可以对存储在其成员变量中的内容有一个整体的控制
- 类的用户不需要知道类是如何存储数据的
static关键字 (类级别的,与对象无关)
- static修饰的全局变量叫静态变量,也叫类变量,被所有的对象所共享,用类名.属性访问;
- static修饰的方法叫静态方法,即类方法;可以直接用类名.方法访问;
- 类只能使用类方法,而不能使用静态变量;
- 类加载以后就存在内存中了,在mian方法执行之前;
- 用static修饰的变量存在堆内存的数据段的静态区中
public static final int MAX = 100;
常量属性定义为static,节约空间
final:因为用final修饰,所以是个常量
public:因为是常量,所以不能更改,public修饰给别人看也没事
static:共享,这样就不用new出来才能使用;
- 静态方法只能访问或调用静态属性和静态方法
- 非静态方法法既能访问调用非静态属性和方法,也能访问静态方法和属性
原因:静态属性和方法在类加载的时候就加载到内存中了,而非静态属性和方法必须绑定在对象上,而对象必须先实例化才能调用;
如果用静态方法访问非静态属性,但是内存中却不存在非静态属性,所以编译器会报错.
代码块
静态初始化块
- 语法:static {语句1;语句2;…;};
- 调用顺序:当类被JVM的类加载器加载的时候执行,
只加载一次,因为JVM只加载一次类.
实例化初始化块
- 语法:{语句1;语句2;…;};
- 调用顺序:在类的对象每次实例化的时候执行一次,在构造器之前调用;
class A {
public String name = "成员属性" ;
static {
System.out.println("静态初始化块");
}
{
this.name = "name";
this.age = 26;
System.out.println("实例初始化块内");
System.out.println(this.name);
System.out.println(this.age);
}
public int age = 10;
public A ( ) {
System.out.println("构造方法内");
System.out.println(name);
System.out.println(age);
}
}
//主方法
class ClassName {
public static void main(String[] args) {
new A();
}
}
输出结果 :
静态初始化块
实例初始化块
name
26
构造方法内
name
10
步骤:
1. 执行到new A();
时,加载A.class到内存中;
2. static随着类的加载而创建(在堆内存的数据段中的静态区中,存放的是静态变量和静态方法,常量存放在堆内存的数据段的常量池中)
3. 输出 静态初始化代码块
4. 执行构造方法时要做的事:
- 在堆内存中申请内存;(size = int + String)
- 分配这块内存;(给name分配4字节空间,因为它是一个引用;给age分配4个字节);
- 初始化这块内存中的变量,
name="成员属性";age=10;
- 调用实例初始化代码块,执行代码块中的语句
name = name,age=26;
- 执行实例代码块后面的语句;
public int age = 10;
- 执行构造方法内的语句 输出
name
和age
的值;
内部类 (先大概了解)
- 在类的里面再定义一个类,这个类就叫内部类;
- 它是一个独立的类;
- 可以产生对象使用;
- 编译后又独立的class文件;
- classA$1classB –>是局部内部类;(比成员内部类少了一个数字,因为一个类有多个方法,在不同的方法里面可以定义相同名字的内部类,为了区分,编译器自动为我们添加你一个数字作为区分)
- classA$classB –>是成员内部类;(把成员内部类作为外部类的属性,属性当然不能重名了,所以成员内部类的名字不能相同)
分类
- 成员内部类 –>定义在外部类中方法外面的类;
- 静态内部类:(成员内部类的一种)
- 局部内部类 –>定义在外部类的方法里面,定义的时候不能加访问修饰符
- 匿名内部类:没名字,主要用于实现接口的方法.
为什么局部内部类不能用访问修饰符修饰?
从内存中看,当方法里的局部变量所在方法结束时,该变量即在栈内存中消失;而内部类其实是一个类,只有内存中对它的所有引用都消失后,该内部类才”死亡”,即内部类的生命周期可能比局部变量长。如果局部内部类能访问一般的局部变量,则在多线程中,可能当方法结束后,局部内部类(是线程类时)还在使用局部变量。为了避免方法内的变量脱离方法而存在的现象发生,于是java规定局部内部类不能访问一般的局部变量。但能访问被final修饰的局部变量。因为常量放在堆内存中的数据段的常量池中