首页 > 代码库 > Java:面向对象--封装

Java:面向对象--封装

1、面向对象的简单说明

 1 /*
 2     事物:
 3     属性    事物的信息描述
 4     行为    事物的功能
 5 
 6     类:
 7     成员变量    事物的属性
 8     成员方法    事物的行为
 9     
10     定义一个类,其实就是定义该类的成员变量和成员方法。
11 
12     手机事物:
13         属性:品牌,价格,颜色...
14         行为:打电话,发短信,玩游戏...
15         
16     手机类:
17         成员变量:品牌,价格,颜色
18         成员方法:打电话,发短信,玩游戏
19         
20     成员变量:和以前变量的定义是一样的格式,但是位置不同,在类中方法外。
21     成员方法:和以前的方法定义是一样的格式,但是今天把static先去掉。
22 */
23 class Phone {
24     //品牌
25     String brand;
26     //价格
27     int price;
28     //颜色
29     String color;
30     
31     //打电话的方法
32     public void call(String name) {
33         System.out.println("给"+name+"打电话");
34     }
35     
36     //发短信的方法
37     public void sendMessage() {
38         System.out.println("群发短信");
39     }
40     
41     //玩游戏的方法
42     public void playGame() {
43         System.out.println("玩游戏");
44     }
45 }

一个对象的内存分布:

技术分享

两个对象的内存分部:

技术分享

三个对象的内存分部:

技术分享

2、成员变量和局部变量的区别

 1 /*
 2     成员变量和局部变量的区别?
 3         A:在类中的位置不同
 4             成员变量:在类中方法外
 5             局部变量:在方法定义中或者方法声明上
 6         B:在内存中的位置不同
 7             成员变量:在堆内存
 8             局部变量:在栈内存
 9         C:生命周期不同
10             成员变量:随着对象的创建而存在,随着对象的消失而消失
11             局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
12         D:初始化值不同
13             成员变量:有默认初始化值
14             局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
15             
16         注意事项:
17             局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
18 */
19 class Varialbe {
20     //成员变量
21     //int num = 10;
22     int num; //0
23     
24     public void show() {
25         //int num2 = 20; //局部变量
26         //可能尚未初始化变量num2
27         //int num2; //没有默认值
28         int num2 = 20;
29         System.out.println(num2);
30         
31         //int num = 100;
32         System.out.println(num);
33     }
34 }
35 
36 
37 class VariableDemo {
38     public static void main(String[] args) {
39         Varialbe v = new Varialbe();
40         
41         System.out.println(v.num); //访问成员变量
42         
43         v.show();    
44             
45     }
46 }

3、形式参数是类名

 1 /*
 2     形式参数的问题:
 3         基本类型:形式参数的改变不影响实际参数
 4         引用类型:形式参数的改变直接影响实际参数
 5 */
 6 //形式参数是基本类型
 7 class Demo {
 8     public int sum(int a,int b) {
 9         return a + b;
10     }
11 }
12 
13 //形式参数是引用类型
14 class Student {
15     public void show() {
16         System.out.println("我爱学习");
17     }
18 }
19 
20 class StudentDemo {
21     //当一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
22     public void method(Student s) { //调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
23         s.show();
24     }
25 }
26 
27 class ArgsTest {
28     public static void main(String[] args) {
29         //形式参数是基本类型的调用
30         Demo d = new Demo();
31         int result = d.sum(10,20);
32         System.out.println("result:"+result);
33         System.out.println("--------------");
34         
35         //形式参数是引用类型的调用
36         //需求:我要调用StudentDemo类中的method()方法
37         StudentDemo sd = new StudentDemo();
38         //创建学生对象
39         Student s = new Student();
40         sd.method(s); //把s的地址给到了这里
41     }
42 }

4、匿名对象

 1 /*
 2     匿名对象:就是没有名字的对象。
 3     
 4     匿名对象的应用场景:
 5         A:调用方法,仅仅只调用一次的时候。
 6             注意:调用多次的时候,不适合。
 7             那么,这种匿名调用有什么好处吗?
 8                 有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
 9         B:匿名对象可以作为实际参数传递
10 */
11 class Student {
12     public void show() {
13         System.out.println("我爱学习");
14     }
15 }
16 
17 class StudentDemo {
18     public void method(Student s) {
19         s.show();
20     }
21 }
22 
23 class NoNameDemo {
24     public static void main(String[] args) {
25         //带名字的调用
26         Student s = new Student();
27         s.show();
28         s.show();
29         System.out.println("--------------");
30         
31         //匿名对象
32         //new Student();
33         //匿名对象调用方法
34         new Student().show();
35         new Student().show(); //这里其实是重新创建了一个新的对象
36         System.out.println("--------------");
37         
38         
39         //匿名对象作为实际参数传递
40         StudentDemo sd = new StudentDemo();
41         //Student ss = new Student();
42         //sd.method(ss); //这里的s是一个实际参数
43         //匿名对象
44         sd.method(new Student());
45         
46         //在来一个
47         new StudentDemo().method(new Student());
48      }
49 }

5、封装和private关键字

 1 /*
 2     private:
 3         是一个权限修饰符
 4         可以修饰成员变量和成员方法
 5         被其修饰的成员只能在本类中被访问
 6 */
 7 class Demo {
 8     //int num = 10;
 9     //用private修饰
10     private int num = 10;
11     
12     public void show() {
13         System.out.println(num);
14     }
15     
16     private void method() {
17         System.out.println("method");
18     }
19     
20     public void function() {
21         method();
22     }
23 }
24 
25 class PrivateDemo {
26     public static void main(String[] args) {
27         Demo d = new Demo();
28         //不能方法私有的成员变量
29         //System.out.println(d.num);
30         d.show();
31         //不能访问私有的成员方法
32         //d.method();
33         d.function();
34     }
35 }
 1 /*
 2     定义一个学生类:
 3         成员变量:name,age
 4         成员方法:show()方法
 5         
 6     我们在使用这个案例的过程中,发现了一个问题:
 7         通过对象去给成员变量赋值,可以赋值一些非法的数据。
 8         这是不合理的。
 9         应该是这个样子的:在赋值之前,先对数据进行判断。
10         判断到底在哪里做比较合适呢?
11         StudentDemo类是一个测试类,测试类一般只创建对象,调用方法。    
12         所以,这个判断应该定义在Student类中。
13         而我们在成员变量的位置可不可以进行数据判断呢?
14         是不可以的,因为做数据校验,必须要依靠一些逻辑语句。
15         逻辑语句是应该定义在方法中的,所以,我们最终决定在Student类中提供一个方法
16         来对数据进行校验。
17     
18     按照我们前面的分析,我们给出了一个方法进行校验。
19     但是呢,它偏偏不调用方法来赋值,还是直接赋值了,
20     这样我们的方法就没有起到作用。
21     我就应该要求你必须使用我的方法,而不能直接调用成员变量赋值。
22     怎么去强制要求不能直接使用成员变量呢?
23         针对这种情况,Java就提供了一个关键字 private
24         
25     private:私有的。可以修饰成员变量和成员方法。
26         注意:被private修饰的成员只能在本类中访问。
27         
28     其实我讲到现在讲解的是一个封装的思想。
29     封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
30 */
31 class Student {
32     //姓名
33     String name;
34     //年龄
35     private int age;
36     
37     //写一个方法对数据进行校验
38     /*
39         返回值类型:void
40         参数列表:int a
41     */
42     public void setAge(int a) {
43         if(a < 0 || age > 120) {
44             System.out.println("你给的年龄有问题");
45         }else {
46             age = a;
47         }
48     }
49     
50     
51     //show()方法,显示所有成员变量值
52     public void show() {
53         System.out.println("姓名:"+name);
54         System.out.println("年龄:"+age);
55     }
56 }
57 
58 class StudentDemo {
59     public static void main(String[] args) {
60         //创建学生对象
61         Student s = new Student();
62         s.show();
63         System.out.println("--------------");
64         
65         //给成员变量赋值
66         s.name = "林青霞";
67         //s.age = 27;
68         s.setAge(27);
69         s.show();
70         System.out.println("--------------");
71         
72         //给age赋值
73         //s.age = -27; //这个数据是不合理的
74         //通过方法给值
75         s.setAge(-27);
76         s.show();
77         System.out.println("--------------");
78     }
79 }
 1 /*
 2     封装和private的应用:
 3         A:把成员变量用private修饰
 4         B:提高对应的getXxx()和setXxx()方法
 5 */
 6 //定义学生类
 7 class Student {
 8     //姓名
 9     private String name;
10     //年龄
11     private int age;
12     
13     //姓名获取值
14     public String getName() {
15         return name;
16     }
17     
18     //姓名设置值
19     public void setName(String n) {
20         name = n;
21     }
22     
23     //年龄获取值
24     public int getAge() {
25         return age;
26     }
27     
28     //年龄赋值
29     public void setAge(int a) {
30         age = a;
31     }
32 }
33 
34 //测试类
35 class StudentTest {
36     public static void main(String[] args) {
37         //创建学生对象
38         Student s = new Student();
39         
40         //使用成员变量
41         //错误:被私有修饰了,外界不能直接访问了
42         //System.out.println(s.name+"---"+s.age);
43         System.out.println(s.getName()+"---"+s.getAge());
44         
45         //给成员变量赋值
46         //s.name = "林青霞";
47         //s.age = 27;
48         //通过方法给赋值
49         s.setName("林青霞");
50         s.setAge(27);
51         System.out.println(s.getName()+"---"+s.getAge());
52     }
53 }

6、this关键字

 1 /*
 2     我们曾经曰:起名字要做到见名知意。
 3     
 4     this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。
 5     
 6         注意:谁调用这个方法,在该方法内部的this就代表谁。
 7         
 8     this的场景:
 9         解决局部变量隐藏成员变量
10 */
11 //定义学生类
12 class Student {
13     //姓名
14     private String name;
15     //年龄
16     private int age;
17     
18     //姓名获取值
19     public String getName() {
20         return name;
21     }
22     
23     //姓名设置值
24     public void setName(String name) { //name = "林青霞";
25         //name = name; //变量的使用规则:就近原则
26         //这里是类名,目前还没有说过类似的用法,所以这个是有问题的
27         //这里的调用只能通过对象名
28         //这个对象如果存在,它应该代表的是Student的一个对象。
29         //那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this
30         //Student.name = name;
31         this.name = name;
32     }
33     
34     //年龄获取值
35     public int getAge() {
36         return age;
37     }
38     
39     //年龄赋值
40     public void setAge(int age) {
41         this.age = age;
42     }
43 }
44 
45 //测试类
46 class StudentTest {
47     public static void main(String[] args) {
48         //创建学生对象
49         Student s = new Student();
50         
51         //给成员变量赋值
52         s.setName("林青霞");
53         s.setAge(27);
54         //获取数据
55         System.out.println(s.getName()+"---"+s.getAge());
56     }
57 }
 1 /*
 2     标准的代码改进版
 3     
 4     this:哪个对象调用那个方法,this就代表那个对象
 5 */
 6 class Student {
 7     private String name;
 8     private int age;
 9     
10     public String getName() {
11         return name; //这里其实是隐含了this
12     }
13     
14     public void setName(String name) {
15         this.name = name;
16     }
17     
18     public int getAge() {
19         return age;
20     }
21     
22     public void setAge(int age) {
23         this.age = age;
24     }
25 }
26 
27 class StudentTest2 {
28     public static void main(String[] args) {
29         //创建一个对象
30         Student s1 = new Student();
31         s1.setName("林青霞");
32         s1.setAge(27);
33         System.out.println(s1.getName()+"---"+s1.getAge());
34         
35         //创建第二个对象
36         Student s2 = new Student();
37         s2.setName("刘意");
38         s2.setAge(30);
39         System.out.println(s2.getName()+"---"+s2.getAge());
40     }
41 }

7、构造方法

 1 /*
 2     构造方法:
 3         给对象的数据进行初始化
 4 
 5     格式:
 6         A:方法名与类名相同
 7         B:没有返回值类型,连void都没有
 8         C:没有具体的返回值
 9 */
10 class Student {
11     private String name; //null
12     private int age; //0
13     
14     public Student() {
15         System.out.println("这是构造方法");
16     }
17 }
18 
19 class ConstructDemo {
20     public static void main(String[] args) {
21         //创建对象
22         Student s = new Student();
23         System.out.println(s); //Student@e5bbd6
24     }
25 }
 1 /*
 2     我们一直在使用构造方法,但是,我们确没有定义构造方法,用的是哪里来的呢?
 3     
 4     构造方法的注意事项:
 5         A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
 6         B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。
 7             注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法
 8         
 9     给成员变量赋值有两种方式:
10         A:setXxx()
11         B:构造方法
12 */
13 
14 class Student {
15     private String name;
16     private int age;
17 
18     public Student() {
19         //System.out.println("我给了,你还给不");
20         System.out.println("这是无参构造方法");
21     }
22     
23     //构造方法的重载格式
24     public Student(String name) {
25         System.out.println("这是带一个String类型的构造方法");
26         this.name = name;
27     }
28     
29     public Student(int age) {
30         System.out.println("这是带一个int类型的构造方法");
31         this.age = age;
32     }
33     
34     public Student(String name,int age) {
35         System.out.println("这是一个带多个参数的构造方法");
36         this.name = name;
37         this.age = age;
38     }
39     
40     public void show() {
41         System.out.println(name+"---"+age);
42     }
43 }
44 
45 class ConstructDemo2 {
46     public static void main(String[] args) {
47         //创建对象
48         Student s = new Student();
49         s.show();//null---0
50         System.out.println("-------------");
51         
52         //创建对象2
53         Student s2 = new Student("林青霞");
54         s2.show();//林青霞---0
55         System.out.println("-------------");
56         
57         //创建对象3
58         Student s3 = new Student(27);
59         s3.show();//null---27
60         System.out.println("-------------");
61         
62         //创建对象4
63         Student s4 = new Student("林青霞",27);
64         s4.show();//林青霞---27
65     }
66 }

8、成员方法

 1 /*
 2     类的组成:成员变量,成员方法
 3     今天我们又加入了一个新的成员:构造方法。
 4     以后再提类的组成:
 5         成员变量
 6         构造方法
 7         成员方法
 8             根据返回值:
 9                 void类型
10                 非void类型
11             形式参数:
12                 空参方法
13                 非空参方法
14 */
15 class Student {
16     public String getString() {
17         return "helloworld";
18     }
19 
20     public void show() {
21         System.out.println("show");
22     }
23     
24     public void method(String name) {
25         System.out.println(name);
26     }
27     
28     public String function(String s1,String s2) {
29         return s1+s2;
30     }
31 }
32 
33 class StudentDemo {
34     public static void main(String[] args) {
35         //创建对象
36         Student s = new Student();
37         
38         //调用无参无返回值方法
39         s.show();
40         
41         //调用无参有返回值方法
42         String result = s.getString();
43         System.out.println(result);
44         
45         //调用带参无返回值的方法
46         s.method("林青霞");
47         
48         //调用带参带返回值的方法
49         String result2 = s.function("hello","world");
50         System.out.println(result2);
51     }
52 }

9、创建对象做了哪些事情

技术分享

10、练习

 1 /*
 2     定义一个类Demo,其中定义一个求两个数据和的方法,
 3     定义一个测试了Test,进行测试。
 4     
 5     变量什么时候定义为成员变量:
 6         如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。
 7         
 8     变量到底定义在哪里好呢?
 9         变量的范围是越小越好。因为能及时的被回收。
10 */
11 
12 //方式1
13 /*
14 class Demo {
15     public int sum() {
16         int a = 10;
17         int b = 20;
18         int c = a + b;
19         return c;
20     }
21 }
22 */
23 //方式1满足了我们的要求,但是不好。
24 //因为参与操作的数据现在是固定的。
25 
26 //方式2
27 /*
28 class Demo {
29     public int sum(int a,int b) {
30         return a + b;
31     }
32 }
33 */
34 
35 //方式2可以满足我们的要求,但是呢我们学习过来面向对象的思想。
36 //我就再想,a,b可不可以定义为成员变量呢?
37 //如果可以,我们再改进一版
38 class Demo {
39     int a;
40     int b;
41     
42     public int sum() {
43         return a + b;
44     }
45 }
46 //虽然这种方式可以,并且好像是符合了面向对象的思想。
47 //但是不好。
48 //因为我们曾经说过:类是一组相关的属性和行为的集合。
49 //并且类是通过事物转换过来的
50 //而类中的成员变量就是事物的属性
51 //属性是用来描述事物的
52 //同理:成员变量其实是用来描述类的。
53 
54 //测试类
55 class Test {
56     public static void main(String[] args) {
57         //创建对象
58         //方式1测试
59         /*
60         Demo d = new Demo();
61         System.out.println(d.sum());
62         */
63         
64         //方式2测试
65         /*
66         Demo d = new Demo();
67         int a = 10;
68         int b = 20;
69         System.out.println(d.sum(a,b));
70         */
71         
72         //方式3测试
73         Demo d = new Demo();
74         d.a = 10;
75         d.b = 20;
76         System.out.println(d.sum());
77     }
78 }

11、static关键字

 1 /*
 2     定义一个人类
 3     
 4     姓名和年龄都是变化的,这个我能接收,因为每个人的姓名和年龄是不同的。
 5     但是,我们现在选取的几个人都是中国人,他们的国籍是一样的。
 6     一样的国籍,我每次创建对象,在堆内存都要开辟这样的空间,
 7     我就觉得有点浪费了。怎么办呢? 
 8         针对多个对象有共同的这样的成员变量值的时候,
 9         Java就提高了一个关键字来修饰:static。
10 */
11 class Person {
12     //姓名
13     String name;
14     //年龄
15     int age;
16     //国籍
17     //String country;
18     static String country;
19     
20     public Person(){}
21     
22     public Person(String name,int age) {
23         this.name = name;
24         this.age = age;
25     }
26     
27     public Person(String name,int age,String country) {
28         this.name = name;
29         this.age = age;
30         this.country = country;
31     }
32     
33     public void show() {
34         System.out.println("姓名:"+name+",年龄:"+age+",国籍:"+country);
35     }
36 }
37 
38 class PersonDemo {
39     public static void main(String[] args) {
40         //创建对象1
41         Person p1 = new Person("邓丽君",16,"中国");
42         p1.show();//姓名:邓丽君,年龄:16,国籍:中国
43         
44         //创建对象2
45         //Person p2 = new Person("杨幂",22,"中国");
46         //p2.show();
47         Person p2 = new Person("杨幂",22);
48         p2.show();//姓名:杨幂,年龄:22,国籍:中国
49         
50         //创建对象3
51         //Person p3 = new Person("凤姐",20,"中国");
52         //p3.show();
53         Person p3 = new Person("凤姐",20);
54         p3.show();//姓名:凤姐,年龄:20,国籍:中国
55         
56         p3.country = "美国";
57         p3.show();//姓名:凤姐,年龄:20,国籍:美国
58         
59         p1.show();//姓名:邓丽君,年龄:16,国籍:美国
60         p2.show();//姓名:杨幂,年龄:22,国籍:美国
61     }
62 }

static内存图解:

技术分享

 1 /*
 2     static的特点:(它可以修饰成员变量,还可以修饰成员方法)
 3         A:随着类的加载而加载
 4             回想main方法。
 5         B:优先于对象存在
 6         C:被类的所有对象共享
 7             举例:咱们班级的学生应该共用同一个班级编号。
 8             其实这个特点也是在告诉我们什么时候使用静态?
 9                 如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
10             举例:
11                 饮水机(用静态修饰)
12                 水杯(不能用静态修饰)
13         D:可以通过类名调用
14             其实它本身也可以通过对象名调用。
15             推荐使用类名调用。
16             
17             静态修饰的内容一般我们称其为:与类相关的,类成员
18 */
19 class Student {
20     //非静态变量
21     int num = 10;
22     
23     //静态变量
24     static int num2 = 20;
25 }
26 
27 class StudentDemo {
28     public static void main(String[] args) {
29         Student s = new Student();
30         System.out.println(s.num);
31         
32         System.out.println(Student.num2);
33         System.out.println(s.num2);
34     }
35 }
 1 /*
 2     static关键字注意事项
 3         A:在静态方法中是没有this关键字的
 4             如何理解呢?
 5                 静态是随着类的加载而加载,this是随着对象的创建而存在。
 6                 静态比对象先存在。
 7         B:静态方法只能访问静态的成员变量和静态的成员方法
 8                 静态方法:
 9                     成员变量:只能访问静态变量
10                     成员方法:只能访问静态成员方法
11                 非静态方法:
12                     成员变量:可以是静态的,也可以是非静态的
13                     成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
14             简单记:
15                 静态只能访问静态。
16 */
17 class Teacher {
18     public int num = 10;
19     public static int num2 = 20;
20     
21     public void show() {
22         System.out.println(num); //隐含的告诉你访问的是成员变量
23         System.out.println(this.num); //明确的告诉你访问的是成员变量
24         System.out.println(num2);
25         
26         //function();
27         //function2();
28     }
29     
30     public static void method() {
31         //无法从静态上下文中引用非静态 变量 num
32         //System.out.println(num);
33         System.out.println(num2);
34         
35         //无法从静态上下文中引用非静态 方法 function()
36         //function();
37         function2();
38     }
39     
40     public void function() {
41     
42     }
43     
44     public static void function2() {
45     
46     }
47 }
48 
49 class TeacherDemo {
50     public static void main(String[] args) {
51         //创建对象
52         Teacher t = new Teacher();
53         t.show();
54         System.out.println("------------");
55         t.method();
56     }
57 }

Java:面向对象--封装