黑马程序员--面向对象

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------



面向对象

面向对象是一种常见的程序结构设计方法。面向对象是相对于面向过程而言,将与其相关的方法,数据放在一起,如冰箱的开关动作封装进冰箱类中,从人将冰箱打开变成命令冰箱打开,:人.开冰箱—>冰箱.开。这可以将许多复杂的问题简单化,将程序员从执行者变成了调用者。

面向过程与面向对象的区别:

面向过程:强调的是功能行为,一种过程,先干啥,再干啥;

面向对象:将功能封装到对象里,强调的是具备某功能的对象;

按照面向对象的思想,可以把任何的东西看做对象。(万物皆对象)

 

 

面向对象的特征

封装(encapsulation)

继承(inheritance)

多态(polymorphism)

 

在面向对象的开发过程中就是不断的创建对象,使用对象,指挥对象做事情。设计过程其实就是在管理和维护对象之间的关系。

 

类与对象的关系

 

java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义,在定义类时其实就是在不断描述现实生活中事物。而对象则是该类事物实实在在存在的个体。

 

定义一个类:在现实生活中如何描述一样事物呢?不外乎描述属性和行为。在java中用class来描述事物也是如此,属性和行为,属性à对应类中的成员变量,行为à对应类中的成员函数。

 

 

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

成员变量:成员变量定义在类中,在整个类中都可以被访问。

成员变量随着对象的建立而建立,存在于对象所在的堆内存中。

成员变量有默认初始化值。

 

局部变量:局部变量只定义在局部范围内,如:函数内,语句内等。

局部变量存在于栈内存中。

作用的范围结束,变量空间会自动释放。

局部变量没有默认初始化值。

 

构造函数

特点:

函数名与类名相同

不用定义返回值类型

不可以写return语句

 

作用:

给对象进行初始化。

多个构造方法是可以以重载的形式存在

 

封装

 

封装的两个含义:

1.把对象的状态和行为看成一个统一的整体,将二者存放在一个独立的模块中(类);

2."信息隐藏", 把不需要让外界知道的信息隐藏起来,尽可能隐藏对象功能实现细节,字段;

在程序中,通常把类中成员私有化(private),并且对外提供setXxx,getXxx方法让其对xxx进行访问。

 

 

 

*单利设计模式:一个类在内存中只存在一个对象:

示例:

package com.itheima;

 

public class SingleDemo {

    public static void main(String[] args) {

       Single1 s1 = Single1.getInstance();

       Single1 s2 = Single1.getInstance();

       System.out.println(s1==s2);

       //true,因为是同一个对象。

       Single2 s3 = Single2.getInstance();

       Single2 s4 = Single2.getInstance();

       System.out.println(s3==s4);

       //true

    }

}

class Single1{

    //饿汉式

    private Single1() {

       // TODO Auto-generatedconstructor stub

    }

    private static Single1 s = new Single1();

 

    public static Single1 getInstance(){

       return s;

    }

}

class Single2{

    //懒汉式

    private static Single2 s = null;

    private Single2(){};

    public static Single2 getInstance(){

       if(s==null){

           s=new Single2();

       }

       return s;

    }

}

 

 

*建议使用饿汉式,懒汉式在多线程中可能会出现两个对象,可以通过加入锁来保证元素唯一性。

 

 

 

this关键字

特点:this代表其所在函数所属对象的引用。

换言之:this代本类对象的引用。

什么时候使用this关键字呢?

当在函数内需要用到调用该函数的对象时,就用this。(确定是外部参数或者内部参数

 

super关键字

1,super和this的用法相同。

2,this代表本类引用。

3,super代表父类引用。

4,当子父类出现相同的成员名时,可以用super进行区分。

5,子类要调用父类构造函数时,可以使用super语句。

6,super必须放在第一句

 

 

 

 

代码示例:

package com.itheima;

 

public class PersonDemo2 {

    public static void main(String[] args) {

       //创建一个person,并且赋予姓名和年龄

       Person2 p = new Person2("zhangsan", 20);

       //调用personeat方法。

       p.eat();

    }

}

class Person2{

    //描述一个人,人都有姓名,年龄等等。。

    //定义人的姓名

    String name;

    //定义人的年龄

    int age;

    //在创建一个人时便要给人赋予姓名年龄等属性。

    public Person2(String name, int age) {

       super();

       this.name = name;

       this.age = age;

    }

   

    //人还有吃饭等行为

    public void eat() {

       // TODO Auto-generatedmethod stub

       System.out.println(name+"eatting..");

    }

}

 

static(静态)关键字

用法:是一个修饰符,用于修饰类成员(成员变量,成员函数)

    当成员变量被静态修饰后,就多了一个调用方式,除了可以被对象调用外还可以直接被类名调用。à类名.静态成员

static关键字:用于修饰成员(成员变量和成员函数)

 

static特点

1,  随着类加载而加载

a)        也就是说静态会随着类的消失而消失,所以它的生命周期最长。

2,  优先于对象存在

a)        明确一点:静态时先存在,对象是后存在的。

3,被所有的对象所共享。

4,  可以直接被类名调用。

 

 

示例变量和类变量的区别:

1,  存放位置:

a)        类变量随着类的加载而存在于方法区中。

b)        实例变量随着对象的建立而存在于堆内存中。

2,  生命周期:

a)        类变量生命周期最长,随着类的消失而消失。

b)        实例变量生命周期随着对象的消失而消失。

 

 

静态使用注意事项

1,  静态方法只能访问静态成员,包括方法和变量。非静态方法即可以访问静态成员又可以访问非静态成员。

2,  静态方法中不可以定义this,super关键字,因为静态优先于对象存在,所以静态方法不可以出现this,super。

3,  主函数是静态的。

 

静态的利与弊

         利:

1,对对象的共享数据进行单独空间的存储,节省空间,没有必要每一个对象都存储一份。

                   2,可以直接被类调用。

         弊:

1,  生命周期长。

2,  访问出现局限性(只能访问静态。)

                  

静态代码块:

         格式:

                   static{

                                     静态代码块中的执行语句。

}

特点:随着类的加载而执行,只执行一次,并优先于主函数,用于给类进行初始化。

 

构造代码块:

直接写在类中的代码块:

优先于构造方法执行,每次实例化对象之前都会执行构造代码块。

 

那么在程序运行中哪个代码块会先运行呢?进行一个小实验:

package com.itheima;

 

public class MethodDemo2 {

    public static void main(String[] args) {

       new Demo6();

       new Demo6();//再次创建对象,发现静态代码块只运行一次。

    }

}

class Demo6{

    public Demo6() {

       // TODO Auto-generatedconstructor stub

       System.out.println("构造方法运行");

    }

    {

       System.out.println("构造方法  块运行");

    }

    static{

       System.out.println("静态代码块运行");

    }

}

/*静态代码块运行

构造方法  块运行

构造方法运行

构造方法  块运行

构造方法运行

*/

 

可以看出 静态代码块>构造方法块>构造方法

 

继承

继承的概述

1,  多个类中存在相同属性和行为时,这些内容抽取到单独一个类中,那么多个类无需再定义这些内容抽取到单独一个类中,那么多个类无须再定义这些属性和行为,只要继承单独的那个类即可。

2,  多个类可以称为子类,单独这个类被称为父类或超类。

3,  子类可以直接访问父类中的非私有的属性和行为。

4,  通过extends关键字,让类与类之间产生继承关系。
class SubDemo extends Demo{}

5,  继承的出现提高了代码的复用性。

6,  继承的出现让类与类之间产生了关系,提供了多态的前提。

 

 

继承的特点:

1,  java只支持单继承,不支持多继承(接口支持。)

a)        一个类只能有一个父类,不可以有多个父类(因为会出现jvm不知道执行谁的方法。)
class subDemo extends Demo{}//OK
class subDemo extends Demo1,Demo2//Error

2,  java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}

3,  定义继承需要注意:

a)        不要仅为了获取其他类中某个功能而去继承。

b)        类与类之间要有所属(”is a”),xx1 是 xx2的一种。

 

函数覆盖

 

1,  子类中出现与父类一模一样方法时,会出现覆盖操作,也称为重写或复写。

2,  父类中的私有方法不可以被覆盖。

3,  在子类覆盖方法中,继续使用被覆盖的方法可以通过super函数名获取。

4,  覆盖注意事项:

a)        覆盖时,子类方法权限一定要大于或等于护理类方法权限。

b)        静态只能覆盖静态。

5,  覆盖的应用:

a)        当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类中专有的内容。

 

 

 

子类的实例化过程

1,  子类中所有的构造函数默认都会访问父类中空参数的构造函数。

2,  因为每一个构造函数的第一行都有个默认的语句:super();

3,  子类会具备父类中的数据,所有要先明确父类是如何对这些数据进行初始化的。

4,  当父类中没有空参数的构造函数时,子类的构造函数必须通过this或super语句指定要访问的构造函数。

5,  当子类继承父类后,每当运行子类父类的无参构造函数都会运行一次。

 

 

package com.itheima;

 

public class ExtendsDemo {

    public static void main(String[] args) {

       Zi z= new Zi();

       z.eat();

       z.sleep();

       z.getId();

    }

}

class Fu{

    public int id = 12345;

   

    public Fu() {

       // TODO Auto-generatedconstructor stub

       System.out.println("furun..");

    }

    public void eat(){

       System.out.println("fueat");

    }

}

class Zi extends Fu{

    public int id = 54321;

    public Zi() {

       // TODO Auto-generatedconstructor stub

       System.out.println("zirun..");

    }

    public void eat(){

       System.out.println("zieat");

    }

    public void sleep(){

       System.out.println("zisleep");

    }

    public void getId(){

       System.out.println("zi id ="+this.id);

       System.out.println("fu id ="+super.id);

    }

}

 

/*fu run..

zi run..

zi eat

zi sleep

zi id = 54321

fu id = 12345

*/

 

final关键字

1,  final可以修饰类,方法,变量。

2,  final修饰的类不可以被继承。

3,  final修饰的方法不可以被覆盖。

4,  final修饰的变量是一个常量,只能被赋值一次。

5,  内部类只能访问被final修饰的局部变量。

 

 

多态

多态:指同一个实体同时具有多种形式

就像是动物,狗,猫等都是动物,动物的多种心态。

当Zi extends Fu 时

Fu f = new Zi();

 

多态的作用:

把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

 

 

示例:

package com.itheima;

 

public class ExtendsDemo2 {

    public static void main(String[] args) {

       Dog d = new HaShiQi();

       d.eat();

    }

}

class Dog{

    public void eat(){

       System.out.println("dog eat");

    }

}

class HaShiQi extends Dog{

    public void eat(){

       System.out.println("HaShiQieat");

    }

}

class ZhangAo extends Dog{

    public void eat(){

       System.out.println("ZhangAoeat");

    }

}

 

基本数据类型

 

基本数据类型的包装类

java中共有8中基本数据类型:

基本数据类型和其对应的包装类如下图:


8个类都是final修饰的(不可被继承)

 

基本数据类型转换为包装类

把基本数据类型→ 包装类:

通过对应包装类的构造方法实现

除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。

包装类→ 基本数据类型

包装类的实例方法xxxValue();    // xxx表示包装类对应的基本数据类型

 

自jdk1.5后java研发出了一种新功能à自动拆箱装箱。

自动装箱:可把一个基本类型变量直接赋给对应的包装类对象或则Object对象

自动拆箱:允许把 包装类对象直接赋给对应的基本数据类型

示例:

Integer i = 3;//装箱

int i2 = i;//拆箱

 

 

 

 

继承—抽象类

 

当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。

但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。

 

抽象类概述

1,  抽象定义

a)        抽象就是从多个事物中将共性的本质的内容抽取出来的。
例如:狼和狗都是犬科动物,犬科就是抽象出来的概念。

2,  抽象类:

a)        java中可以定义没有方法体的方法,该方法的具体实现是由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。

3,  抽象方法的由来:

a)        多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。
例如:狼和狗都有吼叫的方法,可以吼叫的内容是不一样的,所以抽象出来的犬科虽然有吼叫的方法但是却不明确吼叫的细节。

 

抽象类的特点:

1,  抽象类和抽象方法必须用abstract关键字来修饰。

2,  抽象方法只有一个方法声明,没有方法体,定义在抽象类中。
格式:修饰符abstract返回值类型   函数名(参数列表);
      abstract void setDog(String name){}

3,  抽象类不可以被实例化,也就是不可以用new创建对象,原因如下:
抽象类是具体事务抽取出来的,本身并不具备的,没有对应的实例,例如犬科只是一个抽象的概念,真正存在的是狼和狗,而且抽象类即使创建了对象,调用抽象方法也没有意义。

4,  抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则子类也是抽象类。

 

 

抽象类不过是一个或多个抽象方法的类而已,有自己的构造函数,当有abstract抽象关键字时,不能喝private,final,static共存,原因如下:

1,  private:因为abstract方法需要被重写,所以不能修饰为private。

2,  final:因为abstract方法需要被重写,被final修饰的方法是不能被重写的,所以不能同final共存。

3,  static:因为abstract方法没有方法体,静态方法需要对方法体执行内容分配空间,所以不能同static共存。

抽象类实例:

package com.itheima;

 

public class abstractTest {

    public static void main(String[] args) {

       Demo4 d = new Demo4();

       d.setName("zhangsan");

       d.show();

       System.out.println(d);

    }

}

abstract class abstractDemo{

    //创建一个抽象方法。

    abstract void setName(String name);

    abstract String getName();

    //抽象方法中可以定义非抽象方法。

    public  void show(){

       System.out.println("abstractshow");

    }

}

class Demo4 extends abstractDemo{

    //要实现父类抽象方法。

    String name;

    void setName(String name) {

       // TODO Auto-generatedmethod stub

       this.name= name;

    }

 

    String getName() {

       // TODO Auto-generatedmethod stub

       return name;

    }

 

    @Override

    public String toString() {

       return "Demo4[name=" + name + "]";

    }

}

继承—接口

 

抽象类是从多个类中抽象出来的模板,若要将这种抽象进行得更彻底,就得用到一种特殊的“抽象类”→接口;

 

1,  格式:

a)        interface Xxx{}

2,  接口中的成员修饰符是固定的。

a)        成员变量:public static final

b)        成员函数:public abstract

3,  接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。

 

 

接口的特点

1,  接口是对外暴露的规则

2,  接口是程序的功能扩展。

3,  接口可以用来多实现。

4,  类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。

5,  接口与接口之间可以有继承关系。

 

示例:

package com.itheima;

 

public class InterfaceDemo {

    public static void main(String[] args) {

       new Demo5().show();

    }

}

interface Inter1{

    public static final int NUM =1;

    public abstract void show();

}

interface Inter2{

//  public static final int NUM = 3;

    public abstract void show();

}

class Demo5 implements Inter1,Inter2{

 

    @Override

    public void show() {

       // TODO Auto-generatedmethod stub

       System.out.println(NUM);

    }

}

内部类:

将一个类定义在另一个类里面,对里面那个类就称为内部类(内置类,嵌套类)

 

访问特点:

         内部类可以直接访问外部类中的成员,包括私有成员。

         而外部类要访问内部类中的成员必须要建立内部类的对象。

 

内部类的位置

1,内部类定义在成员位置上,可以被private,static成员修饰符所修饰。
                   被static修饰的内部类只能访问外部类中的静态成员。

2,内部类定义在局部位置上,也可以直接访问外部类的成员。
         同时可以访问所在局部中的局部变量,但必须是被final修饰的。

 

匿名内部类

 

 

就是内部类的一种简化写法,和匿名方法一样,可以调用其中的方法等等,但是无法有实例化对象。并且匿名内部类必须是继承或者实现一个外部类或者接口。格式为:

         new外部类名或接口名(){覆盖类或者接口中的代码(也可理解为自定义对象)}

 

简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。

示例:

package com.itheima;

 

public class InnerClassDemo {

    public static void main(String[] args) {

       new Outer().Method();

       //访问非静态内部类中方法。

       new Outer.Inner2().show();

      

       new Outer().Method2();

    }

}

class Outer extends Dog{

    private int x = 4;

    private class Inner{//创建一个私有化内部类。

       int x = 6;

       void show(){

           //内部内访问内部变量和外部变量。

           System.out.println("inner x ="+this.x+" Outer x ="+new Outer().x);

       }

    }

 

    static class Inner2{//静态内部类

       void show(){

           System.out.println("inner2show");

       }

    }

    void Method(){

       Inner in = new Inner();

       in.show();

    }

    void Method2(){

       new Dog()

       {

           int num= 9;

           void show()

           {

              System.out.println("dog shownum = "+num);

           }

       }.show();

    }

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值