醉月风纯
一个即将参加校招的学渣

导航

 

1,什么是面向对象:

  在哲学上说如果要定义一个名词要从其对立面定义,和面向对象对应的是面向过程。举个简单的例子,如果我们要把一头大象装进冰箱里,面向过程的做法是先打开冰箱,再把大象放进去,最后把冰箱关上,这是一个完整的过程。但是面向对象的做法是给冰箱设计三个方法(打开,存储,关闭),我们依次调用者三个方法即可,下面是我们定义的一个车类对象。

public class carDemo{
    public static void main(String[] args){
        car c = new car();//c是局部变量,car中的num是成员变量
        c.setNum(10);   
        c.setColor("blue");
    }
}

public class car {
    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    private int num;
    private String color;
    
    public void run() {
        System.out.println(num+"...."+color);
    }
}

下图是把内存中的区域划分成栈区和堆区,栈区首先是main方法进栈,然后引用变量c也随之进栈,由于c是引用变量,所以其数据存放在堆内存中,堆内存把数据地址传给c,之后main方法执行完成后会弹栈,程序运行完毕。

 

上面提到了成员变量,那么什么是成员变量,它有什么特点,下面把它和局部变量做以区分。

1.1,成员变量和局部变量的区别:

  • 成员变量定义在类中,整个类都可以访问;局部变量定义在函数,语句,局部代码块中,只在所属区域有效。
  • 成员变量存在于堆内存的对象中;局部变量存在于栈内存的方法中。
  • 成员变量随对象的创建而存在;局部变量所在区域在内存中而存在。
  • 成员变量有默认初始化值;局部变量没有默认初始化值。

 匿名对象:没有名字的对象,如new car(),当对象对方法仅进行一次调用的时候,就可以简化为匿名对象,调用完就会被舍弃。

1.2,this关键字

代表当前对象,this就是函数所属对象的引用,哪个对象调用了this所在的函数,this就代表哪个对象。this也可以用于在构造函数中调用其他的构造函数(此时的调用语句只能放在第一行)。

1.3,static关键字

  1. static是一个修饰符,用于修饰成员。
  2. static修饰的成员被所有的对象共享。
  3. static优先于对象存在,因为static的成员随着类的加载就已经存在了。
  4. static修饰的成员多了一种调用方式,可以在不创建对象的情况下直接用 类名.成员的方法调用。
  5. static修饰的数据是共享数据,对象中储存的是特有数据。

静态使用的注意事项:

  •  静态方法只能访问静态成员
  • 静态方法中不可使用this关键字,super也不行
  • 主函数是静态的

下图是调用一个静态方法和普通方法的示意图,右下的区域是内存中的方法区,StaticDemo2中的方法和类分成静态和非静态至于方法区的两边。

 

 

1.4 构造函数

构造函数在对象创建的时候就运行了,可以实行对象的初始化操作。

创建对象都必须要通过构造函数初始化。

一个类如果没有定义过构造函数,那么该类中含有一个默认的空参构造函数。

如果在类中定义了构造函数,那么原有的构造函数就没用了。

 

一般函数和构造函数的区别:

  • 对象创建时就会调用与之对应的构造函数对对象初始化,只会调用一次;对象创建后,需要函数功能的时候调用,可以多次使用。
  • 该对象创建时就已经具备的特征,构造函数的方法名是类的别名。

静态代码块

static{
    System.out.println("I'm static code");//随着类的加载而执行,主要的作用是对类做初始化操作。
}

  

 1.5 单例模式

设计模式:对问题行之有效的解决方式,其实就是一种思想。

下面简单说下单例设计模式。就是可以保证一个类在内存中的对象唯一性。必须对多个程序使用同一个数值的对象时,即是要保证该对象的唯一性

如何保证:

  • 不允许其他程序使用new来创建该类对象。
  • 在该类中创建一个本类实例。
  • 对外提供一个方法让其他程序可以获取该对象。

 2,封装

首先,属性能够描述事物的特征,方法能够描述事物的动作。封装就是把同一类事物的共性(包括属性和方法)归到同一类中,方便使用。

  1. 封装:封装也称信息隐藏,是指利用抽象数据类型把数据和基于数据的操作封装起来,使其成为一个不可分割的整体,数据隐藏在抽象数据内部,尽可能的隐藏数据细节,只保留一些接口使其与外界发生联系。也就是说用户无需知道内部的数据和方法的具体实现细节,只需根据留在外部的接口进行操作就行。
  2. 封装的好处:

·······1)        实现了专业的分工

·······2)        良好的封装能够减少耦合

·······3)        类内部的结构能够自有修改

·······4)        可以对成员进行更精确的控制

·······5)        隐藏信息,实现细节

封装的步骤

  • 修改属性的可见性来限制对属性的访问
  • 为每个属性创建一队赋值和取值方法,用于对这些属性的访问
  •  在赋值和取值方法中,加入对属性的存取限制  

为了实现良好的封装,我们通常将类的成员变量声明为private,在通过public方法来对这个变量来访问。对一个变量的操作,一般有读取和赋值2个操作,,我们分别定义2个方法来实现这2个操作,一个是getXX(XX表示要访问的成员变量的名字)用来读取这个成员变量,另一个是setXX()用来对这个变量赋值,上面的代码就是封装的体现。

 3,继承

Java继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个父类,易于管理程序,父类是子类的一般化,子类是父类的特化(具体化)

继承所表达的就是一种对象类之间的相交关系,它使得某类对象可以继承另外一类对象的数据成员和成员方法。若类B继承类A,则属于B的对象便具有类A的全部或部分性质(数据属性)和功能(操作),我们称被继承的类A为基类、父类或超类,而称继承类B为A的派生类或子类。

继承避免了对一般类和特殊类之间共同特征进行的重复描述。同时,通过继承可以清晰地表达每一项共同特征所适应的概念范围——在一般类中定义的属性和操作适应于这个类本身以及它以下的每一层特殊类的全部对象。运用继承原则使得系统模型比较简练也比较清晰。

 

4,多态

  方法的重写、重载与动态连接构成多态性; 

  Java之所以引入多态的概念,原因之一是它在类的继承问题上和C++不同,后者允许多继承,这确实给其带来的非常强大的功能,但是复杂的继承关系也给C++开发者带来了更大的麻烦,为了规避风险,Java只允许单继承,派生类与基类间有IS-A的关系(即“猫”is a “动物”)。这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概念以弥补这点的不足,此外,抽象类和接口也是解决单继承规定限制的重要手段。同时,多态也是面向对象编程的精髓所在。 

  要理解多态性,首先要知道什么是“向上转型”。 

  我定义了一个子类Cat,它继承了Animal类,那么后者就是前者的父类。我可以通过

  Cat c = new Cat();       例化一个Cat的对象,这个不难理解。

  但当我这样定义时: Animal a = new Cat();

  这代表什么意思呢?

  很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。所以, 

  父类引用只能调用父类中存在的方法和属性,不能调用子类的扩展部分;因为父类引用指向的是堆中子类对象继承的父类;(但是如果强制把超类转换成子类的话,就可以调用子类中新添加而超类没有的方法了。) 

  同时,父类中的一个方法只有在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用; 

  对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。

 

 
 

 

 

 

 

 

posted on 2018-01-16 20:53  醉月风纯  阅读(132)  评论(0编辑  收藏  举报