前言
封装是实现面向对象的基础,深入的理解封装的特性,有利于我们能更好的领悟面向对象的思想以及实现面向对象编程。
一、对象与引用
Java 语言中除基本类型之外的变量类型都称之为引用类型,对象是通过引用对其操作的。
public class Car{
String color;
String name;
String model;
}
Car car= new Car();
通常把这条语句的动作称之为创建一个对象,其实,它包含了三个动作。
1)右边的“new Car()”,是以Car类为模板,调用Car类的构造函数,在堆空间里创建一个Car类对象。
2)左边的“Car car”创建了一个Car类型引用变量。所谓Car类的引用,就是以后可以用来指向Car
对象的对象引用。
3)”=”操作符使对象引用指向刚创建的那个Car对象。
总结:我们需要通过对象引用来间接访问对象。对象好比是一只很大的气球,但是我们抓不住它。引用变量是一根绳,可以用来系汽球。
二、static关键字
static被称为静态,可以用来修饰类的属性,方法,代码块,内部类。
1.随着类的加载而加载
2.优先于对象存在
3.修饰的成员,被所有对象所共享
4.可不创建对象,直接被类调用
注意:静态属性是类的所有对象共享的,即不管创建了多少个对象,静态属性在内存中只有一个。
public class Chinese {
String name;
int age;
static String country="中国";
public static void print1(){ //静态方法只能调用静态的变量,因为不是静态的变量在对象加载时才加载,而静态方法在类加载中优先加载
System.out.println(country);
}
public void print2(){
System.out.println(country); //非静态方法也可以调用静态变量;因为
}
}
public class ChineseTest {
public static void main(String[] args) {
/* static :
随着类的加载而加载
优先于对象存在
修饰的成员,被所有对象所共享
可不创建对象,直接被类调用*/
/* Chinese c1=new Chinese();
c1.age=20;
c1.name="金子豪";
System.out.println(c1.country); //静态属性由类所有,所有对象共享一份;
Chinese c2=new Chinese();
c2.age=30;
c2.name="张三";
System.out.println(c2.country);*/
Chinese.print1(); //使用类名直接调用静态方法;.
//Chinese.print2(); 不是静态方法,不能用类名直接调用;
}
}
1.static方法可以使用对象调用,也可以直接用类名调用,建议用类名直接调用
2.在static方法内部只能访问类的static属性,不能访问类的非static属性,static属性先加载。
注意:静态方法不可以调非静态全局变量,从内存的角度看,就是当类被加载的时候静态方法和静态属性(全局静态变量)被加载到内存中,就是在内存中开辟一段内存地址用来保存静态方法和静态属性,这时候没有被实例化的类在内存中是不存在的,所以静态方法是不能访问非静态的全局变量。在类被实例化的时候,就是new 某个类的时候,在内存中给这个类开辟一些内存 空间保存这个类的对象,这个时候就可以用静态方法去访问非静态的全部变量。
三、代码块
代码块在类中声明,类似一个没有名称的方法体(代码块),代码分实例块和静态块。
1.实例块
实例块:每次创建对象时自动调用
{
任何符合语法的Java代码
}
2.静态块
静态块:类加载时自动调用,仅一次,与是否创建对象无关。
static {
//任何符合语法的Java代码
}
public class Car {
static int price;
static String name;
//类加载时按照静态的顺序依次调用;
//对象加载时先调用实例块(因为new的时候对象已经被创建构造方法在其后)然后调用构造方法;
//静态块只调用一次,与是否创建对象无关
//实例块每次创建对象会自动调用;
public Car(){
System.out.println("调用了无参的构造方法");
this.price=100;
}
static{
System.out.println("静态代码块1");
}
{
System.out.println("实例块");
}
static{
System.out.println("静态代码块2");
}
}
public class CarTest {
public static void main(String[] args) {
//类什么时候被加载?1.创建对象时 2.使用类名调用方法时 3.使用类名调用属性时 4.main方法在类的内部时
// Car car1=new Car(); 创建对象时加载类
// System.out.println(Car.price); 调用属性时加载类;
Car car1=new Car();
Car car2=new Car();
}
}
注意:实例代码块实际上是被放到了构造方法中,且实例代码块会转换到构造方法的第一行,所以普通代码块比构造方法执行顺序靠前。
创建对象的过程:在我们使用new关键字创建一个对象的时候
1.jvm会先去加载这个对象的类的字节码文件,并把其中static的属性放到方法区保存,此时这些属性还是其类型对应的默认值,(static final的变量除外,jvm会直接对其赋值)。
2.紧接着jvm会对这些方法区中的static变量进行赋值。
3.在方法区中static属性赋值完成后,new关 键字就会在堆中去申请一块空间 用来存储对象,此时对象中的成员属性就正式在内存中存在了,但会被赋予其类型的默认值。
4.在new关键字在堆中开辟内存空间后,jvm就会去调用对象的构造方法,在构造方法中对成员属性开始赋值,当构造方法执行完毕,成员属性也随之完成了赋值。到这里,整个对象的创建过程就算结束了。
四、包
包(package)的命名规范:
第一级 指该项目的类型,如com,org,gov等,
第二级 指项目所开发或者运行的公司名称,如:oracle,sun,huawei等
第三级 指项目的名称,如:bcms,oa,erp,cms等
第四级 指项目模块的名称,如:bean,action,exception等
1.在包名中,可以使用.号来区分包的级别;包名一般情况下是小写
2.包可以更好得管理逻辑相关的类,可以控制不同包之间的访问权限
3.导入外部包的类,关键字import
五、访问权限修饰符
Java语言有四个权限访问修饰符,权限从大到小依次为:
1)public :公共权限 修饰类、属性、方法。可以被任意类访问
2)protected:受保护的权限 修饰属性、方法。
可以被同包类访问,如果不是同包类,必须是该类的子类才可以访问。
3)default:同包权限 修饰类、属性、方法。只能被同包的类访问
4)private:私有权限 修饰属性、方法。 只能在本类中访问
package day2.Demo1;
public class Test {
public int age1;
protected int age2;
int age3;
private int age4;
public static void main(String[] args) {
Test t1=new Test();
System.out.println(t1.age1);
System.out.println(t1.age2);
System.out.println(t1.age3);
System.out.println(t1.age4);
}
}
package day2.Demo1;
public class Test2 {
public static void main(String[] args) {
Test t1=new Test();
System.out.println(t1.age1);
System.out.println(t1.age2);
System.out.println(t1.age3);
/*System.out.println(t1.age4);*/ //private:私有权限 修饰属性、方法 只能在本类中访问
}
}
package day2.Demo2;
public class Test3 extends day2.Demo1.Test {
public static void main(String[] args) {
Test3 t1=new Test3();
day2.Demo1.Test t2=new day2.Demo1.Test();
//default:同包权限 修饰类、属性、方法。只能被同包的类访问
//protected:受保护的权限 修饰属性、方法。可以被同包类访问,如果不是同包类,必须是该类的子类才可以访问。
System.out.println(t1.age1);
System.out.println(t1.age2);
/* System.out.println(t1.age3);
System.out.println(t1.age4);*/
}
}
六、面向对象特征–封装
封装:把类的某些信息隐藏在类内部,不允许外部直接访问,同时对外界提供一个公共的方法去实现访问。
封装的思想非常主要,例如设计模式的单例模式就是借用了封装的思想,把构造方法私有化,外界不能直接创建对象,需要提供指定的方法去创建。
封装这样做的好处是什么?
1.只能通过规定方法访问
2.隐藏类的实现细节
3.方便加入控制语句
4.方便修改实现
package day2.Demo3;
public class Person {
private String name;
private int age;
private static Person Person1;
private Person(){
}
public static Person getPerson1(){ //使用封装来限制对象的创建;
if(Person1==null){
Person1=new Person();
}
return Person1;
}
public void setAge(int age) { //使用封装来规范数据输入的合理性
if(age>=0&&age<=100){
this.age = age;
}
}
public void setName(String name) {
this.name = name;
}
public int getAge(){
return age;
}
public String getName(){
return name;
}
}
package day2.Demo3;
public class PersonTest {
public static void main(String[] args) {
// Person person1=new Person(); 构造方法已经被私有化,不能使用
Person person1= Person.getPerson1();
person1.setAge(90);
System.out.println(person1.getAge());
person1.setName("金子豪");
System.out.println(person1.getName());
}
}
七、this关键字
this关键字:代表自身类的对象,使用this关键字引用成员变量或者成员方法。
注意:this关键字必须放在非静态方法里面。
在一个类的方法或构造方法内部,可以使用“this.成员变量名”这样的格式来引用成员变量名,常常用来区分同名的成员变量和局部变量
public class Demo{
private int a;
public Demo(int a){
this.a = a;
}
public int getA(){
return a;
}
public void setA(int a){
this.a = a;
}
}
注意:this指代当前对象,只有访问对象的属性和方法用this才有意义,即非静态方法和属性才是实例对象才拥有的。而静态成员和方法是通过类名来访问的,即类的成员和方法。应该很好理解的,静态方法和变量是所有类的实例共享的,是类的东西,不需要实例化就能直接访问的,当然没有必要使用对象的this了。这是面向对象语言的语法规定。
总结
本章主要介绍了对象与引用,static关键字,面向对象的特征封装。在这里要特别注意static修饰的变量和方法和非static修饰的变量和方法的区别。本文的知识点和代码量相对于平衡,大家在记忆的时候要多加练习,从而加深印象。