Java笔记(04):面向对象--封装
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 }
如欢如殇 授以青春鲜活肢体奔忙
如思如忘 驱以老朽深沉灵魂冥想
始自情热激荡 从未敢终于世事炎凉
无能执手相望 无法去尝试结发同床
无力至心死身僵 一息坚强
------
我一直没有放弃,如果你也能看到
修身 修禅