菜单
本页目录
第3单元   面向对象(上)

面向对象基本概念: 封装、继承、多态、抽象
                                类、对象、实例
                                变量(属性)、方法(行为)
                                
3.1   面向对象思想

1、编程(程序)语言两种思想:面向过程,面向对象

(1)面向过程:分析解决问题所需的步骤,用方法(函数)逐一实现,通过调用方法(函数)解决问题。比如:C语言,Fortran语言

(2)面向对象:将构成问题的事物,按一定的规则划分为多个对象,通过调用对象来解决问题。
  
 说明:对象

(1)对象映射现实中的事物

(2)对象由两部分组成:变量(属性)、方法(行为)
     变量(属性):描述对象的属性
                                                             +    描述对象间的关系
     方法(行为):描述对象的行为   

(3)一个Java程序,包含多个对象,通过对象间的相互配合实现程序的功能。
 
2、面向对象三大特点: 封装性、继承性、多态性

(1)封装性:
  
定义:将对象的属性(变量)和行为(方法)绑定在一起,封装在对象内部
作用:信息隐藏和权限设置

(2)继承性:
         
定义:描述类与类的关系。通过继承,可以继续原有类的属性和行为,并能对原有类进行扩展。


         例子: 普通汽车类:普通汽车属性、普通汽车功能
                           |
                          V
                    轿车汽车类: 普通汽车属性、普通汽车功能(继承),轿车汽车属性、轿车汽车功能(扩展)

作用:增强代码复用、扩展性,提高代码开发效率

(3)多态性:

定义:同一个属性或方法,具有不同的表现形式的能力。类型的属性或方法被其他类继承后,具有不同的数据类型或不同的行为(继承、子类重写)

           例子:  Cut  : 理发师:剪发;  演员:停止表演

作用:实现同一属性或方法,不同的表现形式,增强代码扩展性

       
3.2   类与对象

        面向对象思想核心:类和对象:        (属性+行为)
   
类:类是对象的模板,描述所有对象共同的特征和行为
对象:对象是类的具体实例

说明:对象根据类创建,类可以有多个不同对象

        例子: 现实生活中,学生可以是一个类
                    
                    类: 学生类                                                                                                                         
                    对象:张三、李四、王五
                    属性(变量):学号,性别、年龄、身高、体重和家庭住址等
                    行为:吃饭、睡觉、学习、运动和打游戏等

3.2.1   类的定义

        面向对象核心是对象,创建对象的前提,需要定义一个类。)
 
1、类:定义成员变量和成员方法
                成员变量:描述对象共同的属性、特征 (多为名词,后面无成对括号)
                成员方法:描述对象共同的行为  (多为动词或动宾结构,后面有成对括号)
说明:类,第2个引用数据类型

2、类的定义语法:

[修饰符]  class  类名{                               //[]:标识该内容可缺省
      成员变量;
      成员方法;
}

例子:定义一个学生类
class Student {                                                                   //Student类名
        String name;                                                              //成员变量:name,age,sex
        int  age;
        String sex;						
        void read() {                                                               //成员方法:read()  
                System.out.println("大家好,我是" + name);    //在成员方法read()中,直接访问成员变量name
        }
}


3、成员变量与局部变量
(1)成员变量:在类中定义的变量
(2)局部变量:在方法中定义的变量

在类中,允许成员变量与局部变量同名。此时,在方法中通过变量访问的是局部变量,而非成员变量。

例子:
class Student {
        int  age=30;                                                             //成员变量age					
        void read() {                                                      //成员方法:read()  
                 int   age=50;                                            //局部变量 age
                System.out.println("大家好,我" + age+"岁了,我在看书!");    //在成员方法read()中,访问局部变量age, 输出50
        }
}


3.2.2   对象的创建与使用

              若要使用类,必须创建对象。

1、对象的创建
     
      对象创建:声明对象+实例化对象(对象是引用数据类型,使用new关键字创建类的实例对象)
     

方法一:声明和实例化分开:

(1)声明对象语法

类名  对象名称;                             //声明一个对象,且该对象没有没有任何引用,即不对其进行实例化

(2)实例化对象

对象名称=new   类名();                //new关键创建类的实例对象

 
方法二:直接创建对象:声明和实例化同时(推荐):  

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


说明:
(1)赋值号“=”左边声明一个对象(用对象变量名代替)
(2)赋值号“=”右边实例化对象
(3)赋值号“=”作用:将右边实例化对象,在内存中的首地址赋值给对象变量名
         (对象变量名保存在栈内存中,对象成员变量保存在堆内存中)


例子1:声明、实例化

方法一                                                                    方法二
Student stu=null;           
stu=new Student();               <=>            Student stu=new Student();


例子:Student类声明,Student对象创建例子

class Student {                                                                                    //Student类声明
        String  name;                                                             				
        void read() {                                                     
                 int   age=50;                                            
                System.out.println("大家好,我是" +name+",我在看书!");   
        }
}

public class Test{                                                                              //Student类的对象创建
        public static void main(String[] args){
                Student stu=new Student();
        }

}

2、对象的使用
     创建对象后,通过对象变量名和“.”运算符,可以使用对象访问类中的成员变量或成员方法。(“.”:读作调用)

对象的使用语法:

对象名称.属性名
对象名称.方法名

例子3-1      对象的使用
class Student {
	String name;       						// 声明姓名属性
	void read() {  
		System.out.println("大家好,我是" + name);
	}
}
class Example01 {
	public static void main(String[] args) {
                       Student stu1 = new Student(); 		// 创建第一个Student对象
	       Student stu2 = new Student(); 		// 创建第二个Student对象
	       stu1.name = "小明";                 	               // 为stu1对象的name属性赋值
	       stu1.read();                  			// 调用对象的方法
	       stu2.name = "小华";
	       stu2.read();
	}
}

大家好,我是小明
大家好,我是小华


说明:
1、创建两个Student对象,stu1,stu2:两个对象是完全独立的个体,各自拥有类的成员变量和方法
2、对某个对象的属性赋值,不影响其他对象的相应的属性值。



3.2.3   对象的引用传递

类属于引用数据类型:对象变量名保存的是对象在内存的首地址。同一个对象,可以被不同的对象变量引用。

例子3-2:对象的引用传递
class Student {
        String name;       						// 声明姓名属性
        int age;           						// 声明年龄属性
        void read() {  
	System.out.println("大家好,我是"+name+",年龄"+age);
        }
}
class Example02 {
	public static void main(String[] args) {
		Student stu1 = new Student ();     //声明stu1对象并实例化
		Student stu2 = null;                      //声明stu2对象,但不对其进行实例化
		stu2 = stu1;                                   // stu1给stu2分配空间使用权
		stu1.name = "小明";                    // 为stu1对象的name属性赋值
		stu1.age = 20;
		stu2.age = 50;
		stu1.read();                  		// 调用对象的方法
		stu2.read();
	}
}


大家好,我是小明,年龄50
大家好,我是小明,年龄50

说明:
1、stu2=stu1:将stu1变量保存的对象的首地址,赋值给stu2变量。此时变量stu1,变量stu2,引用同一个实例化对象



3.2.4   访问控制

1、类、成员变量和成员方法,有不同的访问控制权限

2、Java提供了4种访问控制权限:

              private------->default------->protected------->public    

访问控制权限级别:    低------->高

(1)private:私有的。私有的成员(成员变量和成员方法),只能在本类中访问。
(2)default:默认的(缺省。成员没有写访问权限,默认是default):默认的成员,能被本类或本包其他类访问(本包),不能被其他包中的类访问。
(3)protected:受保护的。受保护的成员,只能被本包及不同包的子类访问。
(4)public:公有的。公有的成员,被所有类访问。

例子:
public class Test{
        public int aa;
        protected boolean bb;                               
        void   cc(){                                                  //(默认的)cc方法
               System.out.println("包访问权限");
        }
        private  class  InnerClass{                          //(私有的)内部类
       }
}

编译器报错。。。。


注:

1、只有成员变量有访问控制权限,局部变量没有访问控制权限,局部变量只能在其所在的方法内有效,不可能被其他类访问。
2、Java的源文件定义的所有类都没有public修饰,则该源文件名可以是合法文件名。
     如果一个源文件中定义了一个public修饰的类,则该源文件名必须与public修饰的类名相同。


3.3   封装性

3.3.1   为什么要封装

原因: 细节隐藏,访问权限控制。

           细节隐藏:方法的实现细节包装并隐藏起来
           访问权限控制:对类种的成员(变量)和数据进行权限设置,防止外部类随意访问。


例子3-3: Example03

3.3.2   如何实现封装

定义:将对象的状态信息(成员变量和数据)隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类提供的方法实现对内部信息的操作访问。

实现:定义类的时候:私有成员变量,对外提供公有成员方法,来设置和获取私有属性值。

(具体化:私有属性,只能被本类访问;外部类想访问私有属性,只能通过公有方法设置和获取属性值。  设置方法: setter();   获取方法:getter())

例子3-4: Example04

class Student{
        private String name;       					// 声明姓名属性                    属性私有
        private  int age;           					// 声明年龄属性
        public String getName() {                                                                 //   getName():  公有方法,获取私有属性值
               return name;
        }
       public void setName(String name) {                                               // setName():  公有方法,设置私有属性值
              this.name = name;                                                                        //   this.name:成员变量;   name:局部变量
       }
       public int getAge() {
              return age;
       }
       public void setAge(int age) {
             if(age<=0){
                     System.out.println("您输入的年龄有误!");
             } else {
                this.age = age;
            }
       }
       public void read() {  
              System.out.println("大家好,我是"+name+",年龄"+age);
       }
 }

public class Example04 {
       public static void main(String[] args) {
	Student stu = new Student();		// 创建学生对象                   (引用数据类型,创建对象后,会自动赋初值)
	stu.setName("张三");	              	// 为对象的name属性赋值
	stu.setAge(-18);	               	// 为对象的age属性赋值
	stu.read();	                        	// 调用对象的方法
       }
}

大家好,我是张三,年龄0                                  //年龄0:  未对其赋值,为何有值?  (引用数据类型,创建对象后,若没有主动赋值,系统会自动赋初值)


说明:私有成员变量,对外部类提供公有成员方法来设置和获取私有属性值。



3.4   构造方法

问题:创建对象后,为对象属性赋值方法:  1、直接调用对象属性名,通过赋值语句:    对象名.属性名=属性值;
                                                                   2、私有属性,公有方法(setter(),get()方法):   
                                                                   3、构造方法:实例化对象的同时,给对象属性赋值


定义:构造方法(又称构造器):类的特殊成员方法,在类实例化对象时自动调用,为对象的属性赋值。

3.4.1   定义构造方法

构造方法,注意点:
(1)构造方法名必须与类名一致。
(2)构造方法名称前不能有任何返回值类型的声明。
(3)不能在构造方法中使用return返回一个值,但是可以单独写return语句作为方法的结束。

分类:无参构造方法,有参构造方法


例子3-5:  (无参)构造方法
class Student{
         public Student() {                                                              //定义(无参)构造方法
	System.out.println("调用了无参构造方法");
          }
}

public class Example05 {
       public static void main(String[] args) {
                System.out.println("声明对象...");
                Student stu = null;           		                 //声明对象
                System.out.println("实例化对象...");
                stu = new Student();     			//实例化对象,实例化对象时,自动调用构造方法
         }
}


声明对象...
实例化对象...
调用了无参构造方法


例子3-6:  (有参)构造方法
class Student{
        private String name;
        private int age;
        public Student(String n, int a) {                                   //定义(有参)构造方法
        name = n;
        age = a;
   }
        public void read(){
        System.out.println("我是:"+name+",年龄:"+age);
    }
}

public class Example06 {
       public static void main(String[] args) {
              Student stu = new Student("张三",18);    // 实例化Student对象
              stu.read();
      }
}

我是:张三,年龄:18


3.4.2   构造方法重载

方法重载:方法名相同,参数不同(类型或个数不同:3种情况)
构造方法,也可以重载。创建对象时,系统自动调用不同构造方法,为不同属性赋值。


例子3-7:  构造方法重载

class Student{
       private String name;
       private int age;
       public Student() {                                                           //无参构造方法
       } 
       public Student(String n) {                                              //有参构造方法:1个参数
             name = n;
       }
       public Student(String n, int a) {                                    //有参构造方法:2个参数
             name = n;
             age = a;
      }
      public void read(){
             System.out.println("我是:"+name+",年龄:"+age);
       }
}
public class Example07 {
        public static void main(String[] args) {
               Student stu1 = new Student("张三");
               Student stu2 = new Student("张三",18);   // 实例化Student对象
               stu1.read();
               stu2.read();
        }
}

我是:张三,年龄:0
我是:张三,年龄:18

注意:
(1)类中没有定义构造方法,系统自动创建一个无参且无函数体的默认构造方法

class  Student{                                            class Student{
}                                         <=>                          public  Student(){
                                                                            }
                                                                  }
 使用new Student()实例化对象时,系统自动调用默认构造方法

(2)当自定义构造方法后,系统不再提供默认的构造方法
     (建议:自定义构造法方法后,再定义个无参的默认构造方法)

class  Student{
      int  age;
      public  Student(int n){
             age=n;
      }
}
publc class Example08{
       public static void main(String[] args) {                             
               Student stu1 = new Student();                            //编译器报错,有自定义构造方法,系统不再提供默认构造方法
       }
}

编译器报错。。。。

(3)构造方法通常使用public修饰



3.5   this关键字

目的:成员变量与局部变量可能重名,使用this关键字分辨成员变量与局部变量。
作用:
(1)使用this关键字调用本类中的属性(成员变量)
(2)使用this关键字调用本类中的成员方法
(3)使用this关键字调用本类中的构造方法

3.5.1   使用this关键字调用本类中的属性

为解决成员变量与构造方法参数的可读性差,需将变量统一命名,会造成成员变量与局部变量同名,导致名称冲突。

例子3-9:  成员变量与局部变量同名,名称冲突
class Student {
       private String name;                                           // 定义构造方法
       private int age;
       public Student(String name,int age) {
              name = name;
              age = age;
       }
       public String read(){
              return "我是:"+name+",年龄:"+age;
       }
}
public class Example09 {
        public static void main(String[] args) {
                Student stu = new Student("张三", 18);
                System.out.println(stu.read());
     }
 }

我是null,年龄0  (原因:成员变量与参数变量同名,编译器无法确定。解决方法:使用this指代对象属性(成员变量))

例子3-10:  this调用本类成员变量
class Student {
       private String name;                                           // 定义构造方法
       private int age;
       public Student(String name,int age) {
              this.name = name;
              this.age = age;
       }
       public String read(){
              return "我是:"+name+",年龄:"+age;
       }
}
public class Example09 {
        public static void main(String[] args) {
                Student stu = new Student("张三", 18);
                System.out.println(stu.read());
     }
 }

我是张三,年龄18


3.5.2   使用this关键字调用本类中的成员方法

例子:this调用本类成员变量
class Student {
       public void  openMouth(){
              .....
       }
       public void read(){
               this.openMouth();                        //使用this调用本类成员方法,此处this可缺省
       }


3.5.3   使用this关键字调用本类中的构造方法:

原理: 构造方法在实例化对象时,被系统自动调用。若要调用其他构造方法,必须使用this关键字来处理。
语法:

this(参数1,参数2.....)

例子3-11  this调用本构造方法

class Student {
        private String name;
        private int age;
        public Student () {                                                                       //无参构造方法
	System.out.println("实例化了一个新的Student对象。");
         }
        public Student (String name,int age) {                                     //有参构造方法
	this();                                                       // 调用无参的构造方法
                this.name = name;
                this.age = age;
         }
         public String read(){
                 return "我是:"+name+",年龄:"+age;
         }
}
public class Example11 { 
         public static void main(String[] args) {
         Student stu = new Student ("张三",18); // 实例化 Student对象
         System.out.println(stu.read());
         }
}


实例化了一个新的Student对象。
我是:张三,年龄:18


注意:this调用构造方法注意点
(1)只能在构造方法中,使用this调用其他构造方法;不能在成员方法中,使用this调用其他构造方法
(2)在构造方法中,使用this调用其他构造方法,必须位于第一行且只能出现一次;
public Student(String name) {
        System.out.println("实例化了一个新的Student对象。");
        this(name) ;                      //错误,必须在第一行
}
(3)不能在同一个类中的两个不同构造方法中使用this相互调用(原因:死循环)
class Student {
        public Student () {               
                this("张三");                                                       // 调用有参的构造方法
	System.out.println("无参构造方法被调用了。");
         }
        public Student (String name{                                    
	this();                                                                // 调用无参的构造方法
                System.out.println("有参构造方法被调用了。");
         }
}

3.6   代码块

定义:“{}”括起来的一段代码
种类(4类):根据声明关键词和位置:普通代码块、构造代码块、静态代码块、同步代码块


3.6.1   普通代码块
定义:直接在方法或语句中,定义的代码块
作用:限定作用域

例子 
public class Example12{
        public static void main(String[] args) {                               //main()方法后,普通代码块
               {                                                              //局部代码块:在方法中定义的代码块
                     int age=18;                                              //局部变量,只在此局部代码块起作用
                     System.out.println("这是局部代码块。age:"+age);
               }
               int  age=30;
               System.out.println("age:"+age);
        }
}

3.6.2   构造块(构造代码块)

定义:类中直接定义的代码块,与成员变量、成员方法和构造方法同级别。
作用:每次实例化对象时,由系统自动调用构造块。
                      优于
执行顺序:    构造块------->构造方法,且与两者在类中定义位置无关


例子3-12:    构造快
class Student{
        String name;                                                   //成员变量
        {                                                                      //构造代码块,与成员、构造方法同级别
               System.out.println("我是构造代码块");       
         }
        public Student(){                                              //构造方法
               System.out.println("我是Student类的构造方法");
        }
}
public class Example12  {
       public static void main(String[] args) {
              Student stu1 = new Student();    //创建两个对象
              Student stu2 = new Student();
       }
}

我是构造代码块
我是Student类的构造方法
我是构造代码块
我是Student类的构造方法


3.7   static关键字

声明(定义)类,只是描述某类事物的特征(成员变量)和行为(成员方法),并没有产生数据。
只有通过new关键字创建对象时,才会开辟栈内存(对象变量名)和堆内存(对象属性)。

定义:如果类中的某些属性(成员变量),被所有对象共享,将属性(成员变量)声明时,使用static关键字修饰

3.7.1   静态属性:

定义:使用static关键字修饰的属性(成员变量),又称公有属性,全局属性。

作用:只会分配一块内存空间,被所有对象共享,只要修改一次,全部对象该该属性值会发生改变。

静态属性,访问语法:
方法1(类调用静态属性):类名.静态属性名   (推荐:不需要创建对象)
方法2(对象调用静态属性):对象名.静态属性名(必须创建对象)

例子3-13: 静态属性
class Student {
        String name;                    		// 定义name属性
        int age;                         		               // 定义age属性
        String school;    		// 定义school属性
        public Student(String name,int age, String school){
               this.name = name;
               this.age = age;
               this.school=school;
        }
       public void info(){
             System.out.println("姓名:" + this.name+",年龄:" +this. age+",学校:" + school);  
       }
}
public class Example13 {
       public static void main(String[] args) {
              Student stu1 = new Student("张三",18,  "A大学");    // 创建学生对象
              Student stu2 = new Student("李四",19, "A大学");
              Student stu3 = new Student("王五",20, "A大学");
              stu1.info();
              stu2.info();
              stu3.info();
    }
}


例子3-14:静态属性 
class Student {
        String name;                    		// 定义name属性
        int age;                         		               // 定义age属性
        static   String school;    		// 定义school静态属性
        public Student(String name,int age,String school){
               this.name = name;
               this.age = age;
               this.school=school;
        }
       public void info(){
             System.out.println("姓名:" + this.name+",年龄:" +this. age+",学校:" + school);  
       }
}
public class Example13 {
       public static void main(String[] args) {
              Student stu1 = new Student("张三",18,"A大学");    // 创建学生对象
              Student stu2 = new Student("李四",19,"A大学");
              Student stu3 = new Student("王五",20,"A大学");
              stu1.school="B大学";        //对象访问静态属性      //Student.school="B大学";类名访问静态属性(推荐)
              stu1.info();
              stu2.info();
              stu3.info();
    }
}



注意:static只能修饰成员变量,不能修饰局部变量(编译器报错)。
public  class Student{
       public void study(){
              static  int num=10;                 //编译器报错
      }
}


姓名:张三,年龄:18,学校:B大学
姓名:李四,年龄:19,学校:B大学
姓名:王五,年龄:20,学校:B大学

3.7.2   静态方法
    
若想使用类中的成员方法,必须实例化对象。
定义:使用static关键词修饰的成员方法,

作用:不用实例化对象,通过类名直接调用某个成员方法。

静态方法,访问语法:
方法1(类调用静态方法):类名.静态方法名   (推荐,不需要创建对象)
方法1(对象调用静态属性):对象名.静态方法名 (必须创建对象)

说明:静态方法只能访问静态成员(静态成员变量、静态成员方法),不能访问非静态成员。(非静态成员,需创建对象才能访问)

例子3-15:静态方法
class Student {
         private String name;                         		// 定义name属性
         private int age;                              		// 定义age属性
         private static String school = "A大学";   		// 定义school属性
         public Student(String name,int age){
                this.name = name;
                this.age = age;
         }
         public void info(){
                 System.out.println("姓名:" +this.name+",年龄:" + this.age+",学校:" + school);
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public int getAge() {
               return age;
        }
        public void setAge(int age) {
               this.age = age;
        }
       public static String getSchool() {
               return school;
       }
       public static void setSchool(String school) {
              Student.school = school;                                         //类名调用静态属性
      }
}
class Example15 {
       public static void main(String[] args) {
              Student stu1 = new Student("张三",18);      // 创建学生对象
              Student stu2 = new Student("李四",19);
              Student stu3 = new Student("王五",20);
              stu1.setAge(20);
              stu2.setName("小明");
              Student.setSchool("B大学");                                     //类名调用静态方法
              stu1.info();
              stu2.info();
              stu3.info();
       }
}


3.7.3   静态代码块

定义:类中直接定义的使用static关键字修饰的代码块。
作用:通常对成员变量初始化(赋值)。
执行:静态代码块在类加载时执行,且只执行一次(类只加载一次)
                  优于         优于
顺序: 静态代码块------>构造块------>构造方法


例子3-16:静态代码块
class Student{
        String name;    						//成员属性
        {
            System.out.println("我是构造代码块");
        }
        static {
              System.out.println("我是静态代码块");
        }
       public Student(){      				//构造方法
              System.out.println("我是Student类的构造方法");
       }
}
class Example16{
        public static void main(String[] args) {
               Student stu1 = new Student();
               Student stu2 = new Student();
               Student stu3 = new Student();
    }
}

我是静态代码块
我是构造代码块"
我是Student类的构造方法
我是构造代码块
我是Student类的构造方法
我是构造代码块
我是Student类的构造方法