面向对象

3.1 面向对象概念

3.1.1 理解面向对象

(1)面向对象是相对面向过程而言;
(2)面向对象和面向过程都是一种思想;
(3)面向过程:强调的是功能行为,“过程”可以理解为动作。面向对象:重点强调具体的事物,将功能封装进对象,强调具备了功能的对象;
(4)面向对象是基于面向过程的。
例如:将大象装入冰箱,使用面向过程的思想步骤为:
①将冰箱打开(函数1);
②将大象放入(函数2)冰箱;
③关上(函数3)冰箱门。
这些动作便是面向过程的体现。C语言就是使用面向过程思想的语言,编写时都是使用函数(方法,动作)来实现的。
使用面向对象的思想步骤为:
①冰箱打开(fridge.open);
②冰箱存储大象(fridge.storage);
③冰箱关上(fridge.close)。
面向对象强调的是冰箱,而这些动作都是冰箱应该具备的动作。只要找到了冰箱,就可以操作冰箱的这些动作。

3.1.2 面向对象的特点

(1)面向对象是一种思想,是符合现在人们思考习惯的一种思想。
(2)面向对象的出现将复杂问题简单化。
(3)面向对象将过程中的执行者,转换成了指挥者。面向对象基于面向过程,将过程进行封装封装到了对象中。
例如:你去电脑城买电脑,面向过程的思想:①查资料,网络,报纸,了解硬件参数信息;②询价,砍价;③装机,并检查;④运输。
面向对象的思想:找老师(懂行的人)一起陪着去,对象:老师。①老师帮我看看这些信息;②老师帮我询价,砍价;③老师帮我监督;④老师运输。只要指挥老师做事情即可,因为老师具备这些功能。
(4)解决问题时:先找具备所需功能的对象,如果没有就造一个具备所需功能的对象。
例如:人开门,解决问题就是先找到该问题领域中涉及的对象。
①名词提炼法:人、门
②开是一个动作。
开定义在人对象中,还是门对象中呢?这个功能定义在哪个对象中最合适,就定义哪个对象中。最合适:哪个对象最清楚这个功能。开的动作用使用到了门这个事物中的内容比如门轴等。门最清楚开的动作,所以开应该定义门事物中。

3.1.3 面向对象开发,设计,特征

(1)开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
(2)设计的过程:其实就是在管理和维护对象之间的关系。
(3)面向对象的特征:封装(encapsulation)、继承(inheritance)、多态(polymorphism)

3.2 类与对象的关系

3.2.1 类与对象

(1)类是抽象的,它是具有相同特性的事物的总称,例如:手机。
类里有成员变量描述对象的属性,成员方法描述对象的行为。
(2)对象是具体的,它是客观存在的事物,对象即是该类事物实实在在存在的个体例如:iPhone手机。
类就是对象的模板(template),而对象就是类的一个实例(instance)。

3.2.2 类的定义

生活中描述事物无非就是描述事物的属性和行为。如:人有身高,体重等属性,有说话,打球等行为。Java中用类class来描述事物也是如此。其中属性对应类中的成员变量,行为对应类中的成员函数。定义类其实在定义类中的成员(成员变量和成员函数)。
要定义一个JAVA类,要具备三个条件:第一:类名;第二:类的属性,它主要描述类的形态,也就是“有什么”;第三:类的方法,它描述类的行为,也就是能“干什么”。
例如:类名:手机;
属性(“有什么”):屏幕,CPU,外壳
方法(“干什么”):打电话,发短信

public class Telphone{
    //属性
    float screen;
    float cpu;
    //方法
    void call(){
     System.out.println("打电话");
    }
    void sendMessage(){
     System.out.println("发短信");
    }
}

3.2.3 成员变量与局部变量

(1)概念
①成员变量(本类或他类):在类中定义,用来描述对象将要什么,可以被本类的函数或者其他类的函数使用。
②局部变量(本函数中):局部变量只定义在局部范围内,如:函数内,语句内等。
(2) 区别
①作用域不同:局部变量的作用域仅限于定义它的函数。成员变量的作用域在整个类内部都是可见的。
②初始化值。
成员变量:因为在堆内存中,都有默认初始化。
局部变量:没有默认初始化。
③在同一个函数中,不允许有同名局部变量。在不同的函数中,可以有同名局部变量。
④两类变量同名时,局部变量具有更高的优先级。
⑤内存出现的时间和位置不同。
成员变量:当对象创建时,出现在堆内存的对象当中。
局部变量:所属区间被运算时,出现在栈内存中。
⑥生命周期不同。
成员变量:随着对象的出现而出现,随着对象的消失而消失。
局部变量:随着所属区间运算结束,立刻被释放。

3.2.4 对象的创建(类的实例化)与使用

(1)JAVA对象的创建
类名 对象名 = new 类名();
Telphone iphone = new Telphone();
(2)JAVA对象的使用
引用对象的属性:对象名.属性

iphone.screen=5;//给screen属性赋值5

引用对象的方法:对象名.方法名()

iphone.sendMessage();//调用sendMessage()方法

再比如:

class Car//对Car这类事物进行描述
{
    String color = "red";
    int num = 4;
    void show()
    {
        System.out.println("color="+color+"..num="+num);
    }
}
class CarDemo 
{
    public static void main(String[] args) 
    {
        Car c = new Car();//建立对象
        c.color = "black";//对对象的属性进行修改
        c.show();//使用对象的功能
    }
}

3.2.5 对象内存结构

http://m.blog.csdn.net/article/details?id=7651251#modile.qq.com
进入正题前首先要知道的是Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性。所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提。
堆:存放new出来的对象。
常量池:存放字符串常量和基本类型常量(public static final)以及某些情况下的某些基本数据类型封装类。
对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象由垃圾回收器负责回收,因此大小和生命周期不稳定,具有很大的灵活性。

预备知识:
1.一个Java文件,只要有main入口方法,我们就认为这是一个Java程序,可以单独编译运行。
2.无论是普通类型的变量还是引用类型的变量(俗称实例),都可以作为局部变量,他们都可以出现在栈中。只不过普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。

class Car//对Car这类事物进行描述
{
    String color = "red";
    int num = 4;
    void show()
    {
        System.out.println("color="+color+"..num="+num);
    }
}
class CarDemo 
{
    public static void main(String[] args) 
    {
        Car c1 = new Car();//建立对象
        c1.color = "black";//对对象的属性进行修改
        Car c2 = new Car();//建立对象
    }
}

只要是用new操作符定义的实体就会在堆内存中开辟一个新的空间。并每一个对象中都有一份属于自己的属性(该属性便是在类Car中描述事物中有color和num的属性)。通过“对象.对象成员”的方式操作对象中的成员,对其中一个对象的成员进行了修改,和另一个对象没有关系。

3.2.6 对象调用的细节

class Car//对Car这类事物进行描述
{
    String color = "red";
    int num = 4;
    void show()
    {
        System.out.println("color="+color+"..num="+num);
    }
}
class CarDemo 
{
    public static void main(String[] args) 
    {
        Car c1 = new Car();//建立对象
        c1.color = "black";//对对象的属性进行修改
        Car c2 = new Car();//建立对象
    }
}

上述代码执行到“Car c1 = new Car();”时有人误以为是通过“class Car//对Car这类事物进行描述”来创建对象的。事实上,在执行main入口方法时,要通过“Car c1 = new Car();”创建对象,实际上调用了Car.class文件。可以将上述代码编译运行后,再将Car类删除来证明。因为将上述代码编译运行后,生成了Car.class文件,再将Car类删除后,代码执行到“Car c1 = new Car();”时便会自动调用已经生成的Car.class文件。
上述代码执行到“c1.color = "black";” 时有人误以为是将类Car中的color的值改变了。事实上,类Car中的属性只是描述事物中有什么。“c1.color = "black“;”改变的其实是c1指向内存中的对象中的color的值。即“c1.color = "black“;”改变的是对象的属性而不是类的属性。

3.2.7 匿名对象的创建与使用

new Dog().jump(); //创建一个匿名对象并直接调用这个对象的方法(jump)

注意:匿名对象使用完一次后就没有了,下次找不到它。
匿名对象的使用:
(1)当对象对方法进行一次调用的时候,可以使用匿名对象来简化。

//  Car c = new Car();
//  c.run();
new Car().run();

当对对象的成员进行多次调用时,必须起名字。
(2)可以将匿名对象作为实际参数进行传递。

//  Car c = new Car();
    show(new Car());
//定义功能,对汽车进行改装
    public static void show(Car cc) {
        cc.color = "black";
        cc.num = 3;
        cc.run();
}

3.3 封装

3.3.1封装的概念

将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

3.3.2封装的好处

(1)只能通过规定的方法访问数据;
(2)隐藏类的实例细节,方便修改和实现。
【例16-1】类未封装性使用实例。

package com.FengZhuang;
public class Person {
    String name;
    int age;
    void talk(){
    System.out.println("我叫"+name+";我的年龄是:"+age);
    }
}
package com.FengZhuang;
public class Test {
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Person p=new Person();
        p.age=-100;
        p.name="张三";
        p.talk();
    }
}

运行结果:
这里写图片描述

从上面的运行结果可知,给age赋值为-100时,显然是一个不合法的值,最终打印出来就会显示错误的信息。在程序设计时,这是绝对不允许的。于是,我们就会使用封装的思想。

3.3.3封装的实现步骤

(1)修改属性的可见性:设为private;
(2)创建getter/setter方法:用于属性的读写;
(3)在getter/setter方法中加入属性控制语句:对属性值得合法性进行判断。
【例16-2】类封装性使用实例。

package com.FengZhuang;
public class Person {
private String name;//修改属性的可见性:设为private,Test类不能//直接通过创建p对象再使用p.name修改其值
    private int age;
void setName(String name){//创建getter/setter方法:用于属性
//读写
        this.name=name;
    }
    void setAge(int age){
        if(age>0)
        this.age=age;
    }
     String getName(){
        return this.name;
    }
     int getAge(){
         return this.age;
     }
    void talk(){
    System.out.println("我叫"+name+";我的年龄是:"+age);
    }
}
package com.FengZhuang;
public class Test {
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Person p=new Person();
        p.setAge(-100);
        p.setName("张三");
        p.talk();
    }
}

运行结果:
这里写图片描述
当给age赋值为-100时,在Person中的属性里设置了条件,因-100<0,所以-100没有赋值给age.所以age的值仍然是初始值0.这便是用private将属性封装的思想。当然,也可以使用private封装方法。
【注意】

private int age;//私有的访问权限最低,只有在本类中的访问有效。

私有的成员:其他类不能直接创建对象访问,所以只有通过本类对外提供具体的访问方式来完成对私有的访问,可以通过对外提供函数的形式对其进行访问。
记住:私有仅仅是封装的一种体现形式而已。

3.4 构造函数

3.4.1 概念

构造函数是定义在JAVA类中的一个用来初始化对象的函数,构造函数与类必须同名且没有返回值,也不能使用void来修饰。

3.4.2 特点

(1)函数名与类名相同;
(2)不用定义返回值类型;
(3)没有具体的返回值;
(4)任何用class定义的类中,都有一个默认的空参数的构造函数。用于给该类对象进行初始化。如果该类中指定了具体的构造函数,那么默认的构造函数就没有了。

3.4.3 作用

(1)使用new+构造函数 创建一个新的对象,并且自动执行构造函数里的内容。
Telphone iphone = new Telphone();
new:用于在堆内存中开辟空间的关键字,用于创建对象。
Telphone:明确要创建Telphone类的对象。
():创建Telphone类的对象,需要通过哪个构造函数进行初始化。这里需要用到一个无参的构造函数。
(2)给对象进行初始化。
创建的每个对象都是一个实体,每个实体必须要进行初始化后才可以使用。实体的初始化是需要通过动作完成的。这个动作就是构造函数。构造函数作用就是给对象进行初始化。
(3)普通函数的调用通常使用“.”,例如:a.show( ) ,而构造函数不能被直接调用,必须使用new+构造函数的方式在创建对象时才会自动调用。
(4)无参构造函数的使用

package com.gouzao;
public class GouzaoWay {
    GouzaoWay(){                     //创建了一个无参的构造函数
    System.out.println("我是无参构造函数");
}
package com.gouzao;
public class TestGouzaoWay {
    public static void main(String[] args) {
        GouzaoWay a=new GouzaoWay(); 
}
}

运行结果:
我是无参构造函数
从上面我们可以看到,当在main中创建对象时,自动调用了类GouzaoWay的构造函数。
(5)有参构造函数的使用(它可以为初始成员变量赋值)

package com.gouzao;
public class GouzaoWay {
    int a,b,c;
GouzaoWay(int a1,int b1,int c1){  //创建了一个有参的构造函数
        a=a1;
        b=b1;
        c=c1;
        System.out.println("我是有参构造函数");
        System.out.println("a="+a+";b="+b+";c="+c);
    }
}
package com.gouzao;
public class TestGouzaoWay {
    public static void main(String[] args) {
    GouzaoWay p=new GouzaoWay(1,2,3);//通过有参的构造函数调用了构造函数,并且给对象中的成员变量赋初始值
}
}

运行结果:
我是有参构造函数
a=1;b=2;c=3
具体案例见E:\Java demo\GouzaoWay

3.4.4 对象内存初始化(构造函数)

3.5.重载

3.5.1 重载概念

如果同一个类中包含了两个或者两个以上函数名相同,函数参数的个数、顺序或者类型不同的函数(统称为参数列表不同),则称为函数的重载:

public class Chongzai {
    public void show(){                     //show函数无参数
        System.out.println("Welcome!");
        System.out.println("***********");
    }
    public void show(String name){          //重载show函数,一个字符串参数
        System.out.println("Welcome!"+name);
        System.out.println("***********");
    }
    public void show(String name,int age){  //重载show函数,两个参数
        System.out.println("Welcome!"+name);
        System.out.println("age:"+age);
        System.out.println("***********");
    }
    public void show(int age,String name){  //重载show函数,两个参数顺序不同
        System.out.println("Welcome!"+name);
        System.out.println("age:"+age);
    }
}
3.5.2 重载的使用
当调用被重载的函数时,JAVA会根据参数的个数和类型来判断应该调用哪个重载函数,参数完全匹配的函数将被执行。如:
public class TestChongzai {
    public static void main(String[] args) {
        Chongzai a=new Chongzai();
        a.show();
        Chongzai b=new Chongzai();
        b.show("Mike");
        Chongzai c=new Chongzai();
        c.show("Mike",20);
        Chongzai d=new Chongzai();
        d.show(21,"Jack");
    }
}

运行结果:
这里写图片描述

3.5.3 函数重载的现实意义
在现实生活中,函数重载的思想比比皆是。例如,假设类名为“人”,类的行为有“洗”,但是“洗”的总数众多,有洗澡,洗衣服,洗手等等。

class Person{
    void Xi(){
        System.out.println("洗衣服!");
    }
    void Xi(int a){
        System.out.println("洗澡!");
    }
    void Xi(String b){
        System.out.println("洗碗!");
    }
}

3.6 this关键字

this代表其所在函数所属对象的引用,换言之:this代表本类对象的引用。this还可以调用本类中的构造函数。

3.6.1 作用

(1)当局部变量和成员变量同名的时候,可以用this来区分。当定义功能时,功能内部使用到了调用该功能的对象。这时就用this来表示。
(2)使用this调用本类中的构造函数。

3.5.2 区分局部变量和成员变量

使用this调用成员变量(不是局部变量)与成员函数,记住一句话:把this当成一个对象!
我们经常创建一个对象,例如:Dog dog=new Dog(); 其中Dog类中有成员变量:“String name;int age;”当dog 对象调用Dog类中的变量时,通常使用以下方式:“dog.name=”哈哈”;dog.age=3;”我们在使用this时,也可以将this直接看成一个对象,例如有以下代码:

package com.ThisExample;
public class ThisExample {
    String name;
    void talk(){
    System.out.println("my name is:"+this.name); //this可看成一个对象,调用了ThisExample类中的成员变量name,这里this可以省略
}
}
package com.ThisExample;
public class TestThisExample {
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        ThisExample a=new ThisExample();
        a.name="哈哈";
        a.talk();
    }
}

运行结果:
这里写图片描述
有一种情况this不可以省略:

package com.ThisExample2;
public class ThisExample2 {
    String name;
    void talk(String name){
System.out.println("my name is:"+name); 
}
}
package com.ThisExample2;
import com.ThisExample.ThisExample;
public class TestThisExample2 {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
            ThisExample2 b=new ThisExample2();
            b.name="哈哈";
            b.talk("哦哦");
        }
}

运行结果:
my name is:哦哦
可以发现,程序中并没有调用成员变量,若要调用成员变量,必须将name改成this.name,即可以看成this这个对象调用了成员变量name.当函数中参数列表的名称与成员变量名称一致时,可以使用this区分两者。例如:

public class Person{
    String name;
int age;
String address;
    void Person(String name,int age ,String address){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
this.address=address; //将参数列表中的address赋值给成员变量address
}
}

3.6.3 调用本类中构造函数

this还有另外一个重要的作用,就是调用本类中的构造函数。构造函数之间的调用可以使用this关键字,后面跟上小括号,指定具体的实参即可明确要调用的构造函数。
注意:调用本类中构造函数的this语句必须定义在构造函数的第一行,因为初始化动作要先完成。

public class Person{
    String name;
int age;
String address;
void Person(String name,int age){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
void Person(String name,int age ,String address){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
this.address=address; //将参数列表中的address赋值给成员变量address
}
}

可以发现以上代码重复较多,而面对对象程序设计最重要的一点就是要减少重复代码,于是,我们可以改写如下:

public class Person{
    String name;
int age;
String address;
void Person(String name,int age){
this.name=name; //将参数列表中的name赋值给成员变量name
this.age=age; //将参数列表中的age赋值给成员变量age
void Person(String name,int age ,String address){
this(name,age)//直接调用上一个构造函数,减少代码重复
this.address=address; //将参数列表中的address赋值给成员变量address
}
}

3.7 局部代码块和构造代码块

局部代码块一般定义在函数中,它控制变量的生命周期。执行完局部代码块,局部代码块内的局部变量就消失了。
构造代码块一般定义在类中,它可以给所有对象进行初始化。创建一个对象,构造代码块就执行一次。
构造代码块与构造函数的区别:给所有的对象初始化!只要创建一个对象,构造代码块就执行一次。构造函数只对对应的对象初始化!

class Person
{
    private String name;
    private int age;
    {//构造代码块(定义在类中),它可以给所有对象进行初始化。
        System.out.println("cons code run");
        cry();
    }
    Person()//对对应的对象进行初始化。 
    {
        System.out.println("Person run");
//      cry();
    }
    Person(String name,int age)
    {
        this.name = name;
        this.age = age;
        System.out.println(this.name+":::::"+this.age);
//      cry();
    }
    public void  cry()
    {
        System.out.println("哇哇...");
    }
}
class ConsCodeDemo 
{
    public static void main(String[] args) 
    {
        Person p = new Person();
        Person p1 = new Person("lisi",29);
        {//局部代码块(定义在主函数中),控制变量的生命周期。
            int x = 9;
        System.out.println("x="+x);
        }
    }
}

3.8 static关键字

用于修饰成员(成员变量和成员函数)与代码块。

3.8.1 静态成员变量

(1)被static修饰的成员变量,被所有对象所共享;
(2)静态随着类的加载而加载,随着类的消失而消失;
(3)优先于对象存在;
(4)静态成员可以直接被类名所调用。
因为静态成员变量随着类的加载而加载,随着类的消失而消失,优先于对象存在。所以,静态成员变量可以使用类名直接访问,也可以使用对象名进行访问。

package com.staticExample;
public class Helloworld {
    static String speak="Hellowold!";
    public static void main(String[] args) {
        //静态变量可以直接使用类名访问,无需创建对象
        System.out.println("通过类名访问speak"+Helloworld.speak);
        //使用对象名访问静态变量
        Helloworld a=new Helloworld();
        System.out.println("通过对象名访问speak:"+a.speak);
        //通过对象名修改静态变量的值
        a.speak="Exchange";
        Helloworld b=new Helloworld();
        System.out.println("通过类名访问speak:"+b.speak);
    }
}

运行结果:
这里写图片描述
注意:我们可以基于一个类创建多个对象,每个对象拥有自己的成员变量,互相独立;static修饰的成员变量属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。

3.8.2 静态成员函数

与静态变量一样,可以使用类名调用静态函数,也可以通过对象名调用。

package com.staticExample;
public class Helloworld2 {
    //使用static关键字声明静态函数
    public static void print(){
        System.out.println("我是静态函数!");
    }
    public static void main(String[] args) {
    //直接使用类名调用静态函数
        Helloworld2.print();
    //也可以通过对象名调用
        Helloworld2 a=new Helloworld2();
        a.print();
    }
}

运行结果:
这里写图片描述
注意:静态函数中不能直接调用非静态成员变量!不能调用普通成员变量!

package com.staticExample;
public class Helloworld3 {
    String name1="Mike";//普通成员变量
    static String name2="迈克";//静态成员变量
    public static void main(String[] args) {    
    System.out.println("不能直接调用非静态变量:"+name1);
    System.out.println("直接调用静态变量:"+name2);  
    }
}

3.8.3 静态代码块

static {
    ......
}

静态代码块在类加载时就执行,且只会执行一次。同时,静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。

package com.staticExample;
public class Helloworld4 {
    int num1;//声明普通成员变量num1
    int num2;//声明普通成员变量num2
    static int num3;//声明静态变量num3
    public Helloworld4(){//构造函数
        num1=91; //声明局部成员变量num1
        System.out.println("通过构造函数为变量num1赋值");
//(第三步:构造函数最后执行)
    }
    {//初始块(第二步:在其次执行)
        num2=71;
        System.out.println("通过构造函数为变量num2赋值");
    }
    static{//静态初始块(第一步:首先执行)
        num3=83;
        System.out.println("通过静态初始块为静态变量num3赋值");   
    }
    public static void main(String[] args) {
        Helloworld4 a=new Helloworld4();//立马加载构造函数
        System.out.println("num1:"+a.num1);
        System.out.println("num2:"+a.num2);
        System.out.println("num3:"+num3);
        Helloworld4 b=new Helloworld4();//立马再次加载构造函数
                                        //不会再次加载静态初始块 
    }
}

运行结果:
这里写图片描述
通过输出结果,我们可以看到,程序运行时静态初始块最先被执行,然后执行普通初始块,最后才执行构造方法。由于静态初始块只在类加载时执行一次,所以当再次创建对象b时并未执行静态初始化块。

3.8.4 使用注意事项

(1)静态方法只能调用静态成员,不能调用非静态成员;
非静态方法可以调用静态成员,也可以调用非静态成员。
(2)在静态方法中不允许出现this,super关键字;
this代表对象,而静态方法执行时还没有对象呢!static对象可以在它的任何对象创建之前访问。
(3)主函数是静态的。
静态是有访问局限性的,只能访问静态的内容。
3.8.5 静态成员变量和非静态成员变量的区别
(1)非静态成员变量又称为实例变量;
静态成员变量又称为类变量。
(2)非静态成员变量,随着对象的创建而存在,随着对象的消失而消失;
静态成员变量,随着类的加载而存在,随着类的消失而消失。

(3)非静态变量存在于对象堆内存中;
静态变量存在于方法区中。
(4)非静态变量只能被对象所调用;
静态变量可以被类名调用,也可以被对象调用。

3.9 面向对象思维模式

(1)对象——首先确定谁去做,其次考虑怎么做。(买饭)
(2)整体与局部——首先考虑整体,其次考虑局部。(电梯:整体(电梯的行为:升降停),局部(电机,门,绳索))
(3)具体与抽象——首先考虑抽象,其次考虑具体。(学东西:首先确定要好好学习,其次可以去图书馆看书,请教他人)(类(手机)是抽象的,对象(iphone)是具体的)
3.10 面向对象设计的终极目标
减少重复代码
3.11 面对对象的三个基本特征
继承,封装,多态
(1)继承
如果类B具有类A的全部属性和方法,而且又具有自己特定的某些属性和方法,则把类A称作一般类,B称作特殊类。
特殊类(B)的对象拥有一般类(A)的全部或部分属性和方法,称特殊类对一般类的继承。
我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。
继承的特征:
①传递性;
②清晰地体现了类之间的层次结构关系;
③提供软件复用功能;
④易于维护;
⑤提供多重继承机制。从理论上说,一个特殊类可以继承多个一般类,这便是多重继承。而Java出于安全性和可靠性的考虑,仅支持单继承,而通过使用借口机制来实现多重继承。
(2)封装
封装(Encapsulation)是将代码及其处理的数据绑定在一起的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。理解封装性的一个方法就是把它想成一个黑匣子,它可以阻止在外部定义的代码随意访问内部代码和数据。对黑匣子内代码和数据的访问通过一个适当定义的接口严格控制。
(3)多态性
多态性(Polymorphism,来自于希腊语,表示“多种形态”)是允许程序中出现重名的现象。Java语言中含有方法的重载与成员覆写两种形式的多态。
方法重载:在一个类中,允许多个方法使用同一个名字,但方法的参数不同,完成的功能也不同
成员覆写:子类与父类允许具有相同的变量名称,但数据类型不同,允许具有相同的方法名称,但完成的功能不同。

3.12 包与访问权限

3.12.1 包的概念与使用

当一个大型程序由多个不同的组别或人员共同开发时,用到相同的类名称是很有可能的事。如果这种情况发生,还要确保程序可以正确运行,就必须通过package关键字来帮忙了。
package是在使用多个类或接口时,为了避免名称重复而采用的一种措施。一般在类或接口的最上面一行加上package的声明就可以了,package的声明如下:
package 名称;
经过package的声明之后,同一文件内的接口或类就会被纳入package中。
注意:包名的写法规范:所有字母都小写。

//package cn.njupt.pack.demo;

包是一种封装形式,用于封装类,想要被包以外的程序访问,该类必须public;
类中的成员,如果被包以外访问,也必须public;
包与包之间访问可以使用的权限有两种:
1:public
2:protected:只能是不同包中的子类可以使用的权限。

注:(1)不写权限修饰符就是default权限。
(2)protected权限和default拥有一样的权限,并且可以在不同包子类(必须有继承关系!)中使用,但protected只能修饰成员函数与成员变量,不能修饰类!

3.12.2 import语句的使用

如果几个类分属于不同package,在某个类要访问到其他类的成员时,则必须做以下修改:
①若某个类需要被访问时,则必须把这个类公开出来,也就是说需要将此类声明成public。
②若要访问不同package内某个public类的成员时,在程序代码内必须使用import语句明确指明“被访问package的名称.类名称”。

//创建一个包,名称为com.nupt.a
package com.nupt.a;
public class Person {
    public String talk(){
        return "OK!";
    } 
}
//创建一个包,名称为com.nupt.b
package com.nupt.b;
//为访问包com.nupt.a中的Person类,需要使用import
import com.nupt.a.Person;
public class Test {
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Person a=new Person();
        System.out.println(a.talk());
    }
}

运行结果:
OK!

3.12.3 Java的命名习惯

(1)包名中的字母一律小写,如demo.java
(2)类名、接口名应当使用名词,每个单词的首字母大写,如TestPerson。
(3)方法名第一个字母小写,后面的每个单词首字母大写,如talkMySelf()。
(4)常量名的每个字母一律大写,如COUNTER。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值