第三 章面向对象 第一步部分

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三 章面向对象 第一步部分相关的知识,希望对你有一定的参考价值。

一、类与对象的基本概念

类:抽象的概念集合,表示的是一个共性的产物,类之中定义的是属性和行为(方法);

对象:是一种个性的表示,表示一个独立的个体,每个对象拥有自己独立的属性,依靠属性区分不同的对象。

类与对象的区别:类是对象的模板,对象是类的实例,类只有通过对象才可以使用,开发中应该先产生类,再产生对象。类不能直接使用,方法可以直接使用。

二、类与对象的定义

1、类的定义:

在JAVA中定义类,可以使用class关键字完成, 语法为:

1 class 类名称{
2     属性(变量);
3     行为(方法);
4 }

范例:定义一个Person类。

1 class Person {
2     String name;
3     int age;
4 
5     public void tell() {
6         System.out.println("姓名:" + name + ",年龄:" + age);
7     }
8 }

2、对象的定义:

定义完类之后,无法直接使用,要使用,必须依靠对象使用,由于类属于引用数据,对象的定义格式如下:

格式一:声明并实例化对象

类名称   对象名称   =  new  类名称  ()

格式二:分布完成

声明对象:     类名称   对象名称 = null;

实例化对象:  对象名称 =  new  类名称();   

以后只要是引用数据类型的实例化操作,永远都会存在关键字new(分配空间)。当一个实例化的对象产生后,可以按照如下方式进行类的操作:

  • 方法.属性:表示调用类之中的属性
  • 方法.对象():表示调用类之中的方法

范例1:使用对象操作类

 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 }
 9 
10 public class TestPerson {
11     public static void main(String[] args) {
12         Person1 per = new Person1();
13         per.name = "张三";
14         per.age = -30;
15         per.tell();
16     }
17 }

姓名:张三,年龄:-30

格式二分步完成操作类,范例2

技术分享
 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 }
 9 
10 public class TestPerson {
11     public static void main(String[] args) {
12         Person1 per = null;
13         per = new Person1();
14         per.name = "张三";
15         per.age = -30;
16         per.tell();
17     }
18 }
View Code

姓名:张三,年龄:-30

格式一与格式二运行结果一致,两者的区别引入内存解释:

堆内存:保存真正的数据

栈内存:保存一块堆内存的空间地址

技术分享

上图为上述程序的内存分析图,过程:声明对象——实例化对象——为对象的name属性赋值——为对象的age属性赋值

范例3、产生两个对象的操作:


 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 }
 9 
10 public class TestPerson {
11     public static void main(String[] args) {
12         Person1 per2 = new Person1();
13         Person1 per1 = null;
14         per1 = new Person1();
15 
16         per1.name = "张三";
17         per2.name = "李四";
18         per1.age = 30;
19         per2.age = 20;
20         per1.tell();
21         per2.tell();
22     }
23 }

 


姓名:张三,年龄:30
姓名:李四,年龄:20

技术分享

内存分析图:声明per1,声明并实例化per2——实例化per2——为per1对象属性赋值——为per2对象属性赋值

 范例4、异常代码:

 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 }
 9 
10 public class TestPerson {
11     public static void main(String[] args) {
12         Person1 per1 = null;//只声明,未实例化per1,只有栈内存,没有堆内存
13         per1.name = "张三";
14         per1.age = 30;
15         per1.tell();
16 
17     }
18 }

运行结果:Exception in thread "main" java.lang.NullPointerException(空间指向异常)
              at hello.TestPerson.main(TestPerson.java:15)
这种异常只会在在用数据类型产生,并很常见,解决方案:查找引用数据类型,观察其是否被实例化

引用传递:同一块堆内存空间同时被多个栈内存所指向,不同的栈可以修改同一块堆内存的内容。

范例4:

 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6  




System.out.println("姓名:" + name + ",年龄:" + age); 7 } 8 } 9 10 public class TestPerson { 11 public static void main(String[] args) { 12 Person1 per1 = new Person1(); 13 per1.name = "张三"; 14 per1.age = 20; 15 Person1 per2 = per1; 16 per2.name = "李四"; 17 per1.tell(); 18 19 } 20 }

姓名:李四,年龄:20

技术分享

范例5:

 1 class Person1 {
 2     String name;
 3     int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 }
 9 
10 public class TestPerson {
11     public static void main(String[] args) {
12         Person1 per1 = new Person1();
13         Person1 per2 = new Person1();
14         per1.name = "张三";
15         per1.age = 20;
16         per2.name = "李四";
17         per2.age = 30;
18         per2 = per1;
19         per2.name = "王五";
20         per1.tell();
21 
22     }
23 }

结果:姓名:王五,年龄:20

技术分享

垃圾:在开发程序中,没有任何对象所指向的一块堆内存空间,这块内存空间被称为垃圾,所有垃圾等待GC(垃圾收集器)不定期的进行回收与空间的释放。

 3、封装性

范例1:

1 public class Person1 {
2     String name;
3     int age;
4 
5     public void tell() {
6         System.out.println("姓名:" + name + ",年龄:" + age);
7     }
8 }
1 public class TestDemo2{
2     public static void main(String[] args) {
3         Person1 p = new Person1();
4         p.name="王娜";
5         p.age=-30;
6         p.tell();
7     }
8 }

运行结果:姓名:王娜,年龄:-30

虽然年龄不可能为负数,但是依然可以执行,这属于业务逻辑错误,出错的关键是没有检查要设置的内容,检查的第一步是让用户看不见操作的东西,此时,用private关键字,将类中的属性进行私有化操作。

范例2:使用private封装类中属性

 1 class Person4 {
 2     private String name;
 3     private int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 
 9 }
10 
11 public class Person3 {
12     public static void main(String[] args) {
13         Person4 per = new Person4();
14         per.name = "张三";//语法错误,无法访问私有属性
15         per.age = -30;//语法错误,无法访问私有属性
16         per.tell();//对象.方法
17     }
18 }

Exception in thread "main" java.lang.Error: Unresolved compilation problems:
    The field Person4.name is not visible
    The field Person4.age is not visible
    at hello.Person3.main(Person3.java:16)    属性被封装,但是无法被外部操作,为此,如果访问类中的私有属性,按如下形式定义操作方法:
setter(以"private String name"属性为例):public void setName(String n);

getter(以"private String name"属性为例):public void getName().

范例3:编写setter()和getter()方法

 

 1 public class Person {
 2     private String name;
 3     private int age;
 4 
 5     public void setName(String n) {
 6         name = n;
 7     }
 8 
 9     public void setAge(int a) {
10         age = a;
11     }
12 
13     public String getName() {
14         return name;
15     }
16 
17     public int getAge() {
18         return age;
19     }
20 
21     public void tell() {
22         System.out.println("姓名:" + name + ",年龄:" + age);
23     }
24 }
1 public class Person1 {
2     public static void main(String[] args) {
3         Person per=new Person();
4         per.setName("张三");
5         per.setAge(20);
6         per.tell();
7     }
8 }

姓名:张三,年龄:20

虽然以上代码可以访问,但是没有加入验证。在开发时,加入验证是在setter中加入,getter只是简单的将数据返回。

范例4:加入验证

 1 public class Person {
 2     private String name;
 3     private int age;
 4 
 5     public void tell() {
 6         System.out.println("姓名:" + name + ",年龄:" + age);
 7     }
 8 public void setName(String n){
 9     name=n;
10 }
11 public void setAge(int a){
12     if(a>=0&&a<=0){
13     age=a;
14 }
15 }
16 public String setName(){
17     return name;
18 }
19 public int setAge(){
20     return age;
21 }
22     }
1 public class Person1 {
2     public static void main(String[] args) {
3         Person per=new Person();
4         per.setName("张三");
5         per.setAge(-20);
6         per.tell();
7     }
8 }

姓名:张三,年龄:0

年龄是-20,不符合逻辑,故置0.

以后在定义类的时候,所有属性都要编写private封装,封装后的属性如果需要被外部操作,则编写setter()和getter()。

4、构造方法(构造方法是在实例化对象的时候使用,而普通方法是在实例化对象产生之后使用的)

定义:构造方法的名称和类名称保持一致;

         构造方法不允许有返回值声明;

         由于对象实例化操作一定需要构造方法的存在,所以,如果在类中没有明确定义构造方法的话,则会自动生成一个无参,无返回值的构造方法,如果一个类之中已经明确定义了一个构造方法的话,则无实际意义的构造方法就不会自动生成,即一个类之中至少存在一个构造方法。

范例4.1:默认情况下会存在一个无参无返回值的构造方法。

1 class Person(){//类名称首字母大写
2     public Person(){//无参无返回值的方法
3     }
4 }

作用:在对象实例化的时候,通过构造方法为类中的属性初始化。

范例4.2:在类中定义有参构造方法。

 1 public class Person {                                      //类名称首字母大写
 2     private String name;                                   //属性封装
 3     private int age;                                       //属性封装
 4 
 5     public Person(String n, int a) {                       //通过构造方法赋值
 6         setName(n);                                        //设置name属性内容
 7         setAge(a);                                         //设置age属性内容
 8     }
 9 
10     public void tell() {
11         System.out.println("姓名:" + name + ",年龄:" + age);
12     }
13 
14     public void setName(String n) {                         //setter:设置name属性内容
15         name = n;
16     }
17 
18     public void setAge(int a) {                              //setter:设置age属性内容
19         if (a >= 0 && a <= 250) {                            //增加检查
20             age = a;                                         //满足条件赋值
21         }
22     }
23 
24     public String getName() {                                //getter:取得name属性
25         return name;
26     }
27 
28     public int getAge() {                                     //getter:取得age属性
29         return age;
30     }
31 }
1 public class TestDem {
2     public static void main(String[] args) {
3         Person per = new Person("张三", 30);// 声明并实例化对象
4         per.tell();// 对象.方法()
5     }
6 }

姓名:张三,年龄:30

 另外:可以用”this.()方法“表示调用本类中的方法,以下代码与范例4.2中代码一样

1 public Person(String n, int a) {                       //通过构造方法赋值
2         this.setName(n);                         //设置name属性内容
3         this.setAge(a);                           //设置age属性内容
4     }

范例4.3:构造方法重载

 1 public class Person { // 类名称首字母大写
 2     private String name; // 属性封装
 3     private int age; // 属性封装
 4 
 5     public Person() { // 无参构造方法
 6     }
 7 
 8     public Person(String name) {
 9         this.setName(name);
10     }
11 
12     public Person(String n, int a) {
13         setName(n);
14         setAge(a);
15     }
16 
17     public void tell() {
18         System.out.println("姓名:" + name + ",年龄" + age);
19     }
20 
21     public void setName(String n) {
22         name = n;
23     }
24 
25     public void setAge(int a) {
26         if (a >= 0 && a <= 250) {
27             age = a;
28         }
29     }
30 
31     public String getName() {
32         return name;
33     }
34 
35     public int getAge() {
36         return age;
37     }
38 }
public class TestDem {
    public static void main(String[] args) {
        Person per = new Person("张三");// 声明并实例化对象
        per.tell();// 对象.方法()
    }
}

姓名:张三,年龄0

在本程序Person类中定义了三个构造方法,在主类中实例化对象时调用了一个参数的构造,结果只为name赋值,年龄为0.

在一个类中对构造方法重载时,所有的重载方法按照参数的个数由多到少或由少到多

5、匿名对象

按内存关系,对象名称可以被解释为在栈内存中保存,而对象的具体内容(属性)在对内存之中保存,所以匿名对象没有对应的栈内存指向,只能使用一次,一次之后将成为垃圾,并且等待GC回收释放。

范例:

 1 public class Person {
 2     private String name;
 3     private int age;
 4 
 5     public Person(String n, int a) {
 6         name = n;
 7         age = a;
 8     }
 9 
10     public void tell() {
11         System.out.println("姓名:" + name + ",年龄" + age);
12     }
13     // settter、getter省略
14 }
1 public class TestDem {
2     public static void main(String[] args) {
3         new Person("张三", 20).tell();// 匿名对象.方法
4     }
5 }

姓名:张三,年龄20

 

以上是关于第三 章面向对象 第一步部分的主要内容,如果未能解决你的问题,请参考以下文章

什么是面向对象?(通俗易懂)

面向对象软件构造 (Bertrand Meyer 著)

c++面向对象程序设计 谭浩强 第一章答案

php面向对象

面向对象编程OOP

第三模块:面向对象&网络编程基础 第2章 网络编程