面向对象

来源:互联网 发布:sql安全性 编辑:程序博客网 时间:2024/06/05 02:39

面向对象是相对面向过程而言,两者都是一种思想,但面向过程强调的是功能行为。面向对象将功能封装进对象。

同时,面向对象是基于面向过程的。面向对象的特征:封装,继承,多态。

类和对象的关系:类是对现实生活中事物的描述。对象就是实实在在存在的个体。

接下来具体介绍类:

1  成员变量和局部变量:

       成员变量作用于整个类,局部变量作用于函数中或者语句中

       同时成员变量在堆内存中,因为对象的存在,才在内存存在,局部变量:存在栈内存中。

2  封装

     封装,是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。为什么用封装?

     封装的好处:将变化隔离,便于使用,提高安全性。而封装的原则是将不需要对外提供的内容隐藏起来,把属性都隐藏,

    提供公共方法对其访问。、

    类型的变量和方法前面的修饰符有几种,以下是他们的区别

作用域       当前类    同一package   子孙类     其他package

public          √                  √                   √                 √

protected     √                 √                   √                 ×

friendly        √                 √                    ×                 ×

private        √                  ×                    ×                 ×


3  构造函数

   构造函数就是给对象进行初始化,他的特点有:

     函数名与类名相同,不用定义返回值类型,不可以写return语句

  同时一个类中可以有多个构造函数。同时,如果没有定义构造函数,系统会自动加上。当初始化对象,只会调用一个构造方法。

  同时还有一个注意的地方,那就是构造代码块,这个块的执行将先于构造函数的执行。

   this关键字:看上去是用于区分局部变量和成员变量同名的情况,例如:

   Student(String name){//如果调用这个构造方法,name的值将为空

   name = name

   }

   Student(String name){//调用后  name将会被赋值。

    this.name = name;

   }

   所以 this 代表本类的对象。this代表它所在函数所属对象的引用,简单来说,哪个对象调用this所在函数,this就代表哪个对象。

4 static关键字,用于修饰成员变量和函数,他有以下特点:

   随着类的加载而加载,优先于对象存在,被所有对象所共享,可以直接被类名调用。

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

  注意:静态方法只能访问静态成员。静态成员进行单独空间的存储,节省空间。他的缺点是声明周期长,同时具有局限性。

    他也只能访问静态。我们现在经常写的main函数也是静态函数。

   main函数是一个特殊的函数。作为程序的入口,可以被jvm调用。

   public static voidmain(String[] args) 这是main函数,那么这个语句的各个单词是什么意思?

   public是修饰符,static 代表着随着类的加载就已经存在,void 没有返回值  main不是关键字,Sting[] arr 表示一个字符串数组。

   jvm低啊用主函数,传入的是new Sting[0];

   那么什么时候使用静态,因为静态修饰的内容有成员变量和函数,当对象中的出现而来共享数据时,该数据被你静态修饰,

   对象中的特有数据要定义非静态存在于堆内存中。

  静态代码块的特点:随着类的加载,只执行一次。用于给类进行初始化的。例如:

  static

  {

        System.out.println("111");      //优先于主函数执行

  }

  下面是一个例子:

   class StaticCode
  {
    static int num ;
    static 
  {
       num = 10;
  //   num *=3;
       System.out.println("hahahah");
   }
    StaticCode(){}
 
    static void show()
    {
             System.out.println(num);
    }
  }

 

class StaticCodeDemo 

  public static void main(String[] args) 
  {      
    new StaticCode().show(); 
    new StaticCode().show();  
 }
}
当执行主函数,结果是:

hahahah
10
10

说明虽然实例化了2个对象,但静态代码块只执行了一次。

现在有一个问题,我们在一个类中可能有构造代码块,构造方法,静态代码块,那么它的执行顺序又是怎样呢?同样

举一个例子说明:

class Person
{
  private String name; 
  {//构造代码块。可以给所有对象进行初始化的。
 
    System.out.println("constructor code ");
//   cry();
  }
  
  static 
  {
    System.out.println("static code");
  }
  
  Person()//是给对应的对象进行针对性的初始化。 
  {
    name = "baby";
//  cry();
  }
  Person(String name)
  {
    this.name  = name; 
    cry();
  }
  public void cry()
  {
    System.out.println("哇哇");
    
  }
 
  public void speak()
  {
    System.out.println("name:"+name);
  }
 
  static void show()
  {
    System.out.println("show run");
  }
}

 

class StaticCodeDemo 

  public static void main(String[] args) 
  { 
   Person p2 = new Person("旺财"); 
 }
}

执行的结果为:

static code
constructor code
哇哇

说明执行的顺序为:静态代码块,构造代码块,最后才是构造方法。

5 继承
  继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力,
  JAVA不支持多继承,一个类只能有一个父类
  其中,继承中有一个关键字:super值得我们记住。与在之前学习的this进行比较的话。两者有以  下差别:
  当本类的成员和局部变量同名 this区分。
  当子父类中的成员变量同名用super区分父类。下面是关于super的例子:
  class Fu
  {
     private int num = 4;
     public int getNum()
     {
         return num;
     }
  }
 
  class Zi extends Fu
  {
     private int num = 5;
     void show()
     {
        System.out.println(this.num+"....."+super.getNum()); //这里的super.getNum()可以得到父类中num的属性,值为4
     }
  }

  class ExtendsDemo2 
  {
     public static void main(String[] args) 
     {
        Zi z = new Zi();
        z.show();
     }
  }   //打印的结果为:5.....4

  接下来说一下函数地两个重要特性,在开发中我们会经常用到。
  当子父类中出现成员函数一模一样的情况,会运行子类的函数。
  这种现象,称为覆盖操作。这时函数在子父类中的特性。
  函数两个特性:
  1,重载。同一个类中。overload
  2,覆盖。子类中,覆盖也称为覆写。override
  
  覆盖注意事项:
  1,子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。 
  2,静态只能覆盖静态,或被静态覆盖。
  那么,什么时候使用覆盖操作?
  当对一个类进行子类的扩展时,子类需要保留父类的功能声明,
  但是要定义子类中该功能的特有内容时,就使用覆盖操作完成.例子如下:
  class Person
  { 
    void show()
    {    
      System.out.println("Person");
    }
    void live()
    {
      System.out.println("我生活在地球上");
    }
  }
  class Student extends Person
  {
    void show()
    {
      System.out.println("我是一个学生,我的父类为Person");
    }
  }
  public class Fuzi {
 public static void main(String[] args) {
  Student student = new Student();
  student.show(); //这里打印:我是一个学生,我的父类为Person。覆盖了Person类的show方法
  student.live(); //这里打印:我生活在地球上。student并没有写方法去覆盖父类方法。
 }

  }

6 单例模式
  单例模式是一种常用的软件设计模式。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,
  从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
  那么,如何保证对象唯一性呢?
  1,不允许其他程序用new创建该类对象。
  2,在该类创建一个本类实例 
  3,对外提供一个方法让其他程序可以获取该对象。
 
  创建单例模式的步骤:
  1,私有化该类构造函数。
  2,通过new在本类中创建一个本类对象 
  3,定义一个公有的方法,将创建的对象返回。
  同时单例模式还分为两种,一种为饿汉式,一种为懒汉式。
  饿汉式:
  class Single //类一加载,对象就已经存在了。
  {
    private static Single s = new Single();
    private Single(){}
    public static Single getInstance()
    {
      return s;
    }
  }
  懒汉式:
  class Single2   //类加载进来,没有对象,只有调用了getInstance方法时,才会创建对象。
                 //延迟加载形式。 
  {
    private static Single2 s = null;
    private Single2(){}
    public static Single2 getInstance()
    {
      if(s==null)
        s = new Single2();
      return s;
    }
  }
  下面有一个单例模式的例子,可以让你了解对象的唯一性:
  class  SingleDemo
  {
    public static void main(String[] args) 
    {
      Test t1 = Test.getInstance();
      Test t2 = Test.getInstance();
      t1.setNum(10);
      t2.setNum(20);
      System.out.println(t1.getNum());
      System.out.println(t2.getNum());
      //打印的结果是10 20 还是20 20 还是10 10 呢?答案是20 20。由此可见只存在了一个对象。
    }
  }
  class Test
  {
    private int num;
    private static Test t = new Test();
    private Test(){}
    public static Test getInstance()
    {
      return t;
    }
    public void setNum(int num)
    {
      this.num = num;
    }
    public int getNum()
    {
      return num;
    }
  }
 

8 多态。
  多态指同一个实体同时具有多种形式。举个例子说明下:
  class 动物{}
 
  class 猫 extends 动物{}
 
  class 狗 extends 动物 {}
 
  猫 x = new 猫();
 
  动物 x = new 猫();//一个对象,两种形态。
 
  猫这类事物即具备者猫的形态,又具备着动物的形态。
  这就是对象的多态性。

  多态在代码中的体现: 父类或者接口的引用指向其子类的对象。
  多态的好处:
    提高了代码的扩展性,前期定义的代码可以使用后期的内容。
  多态的弊端:
    前期定义的内容不能使用(调用)后期子类的特有内容。 例子如下:
  abstract class Animal {
 abstract void eat();
  }

  class Dog extends Animal {
   void eat() {
  System.out.println("啃骨头");
   }

   void lookHome() {
  System.out.println("看家");
   }
  }

  class Cat extends Animal {
   void eat() {
  System.out.println("吃鱼");
   }

   void catchMouse() {
  System.out.println("抓老鼠");
   }
  }

  class Pig extends Animal {
   void eat() {
  System.out.println("饲料");
   }

   void gongDi() {
  System.out.println("拱地");
   }
  }

  class DuoTaiDemo {
   public static void main(String[] args) {
  Animal a = new Cat(); // 自动类型提升,猫对象提升了动物类型。但是特有功能无法s访问。
        // 作用就是限制对特有功能的访问。
        // 专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。
  a.eat();
                //a.catchMouse();这里写个这个方法会报错,原因向上转型,不用使用子类的特有方法
  // 如果还想用具体动物猫的特有功能。
  // 你可以将该对象进行向下转型。
  Cat c = (Cat) a;// 向下转型的目的是为了使用子类中的特有方法。
  c.eat();
  c.catchMouse();
  method(new Dog());
   }

   public static void method(Animal a)// Animal a = new Dog();
   {
  a.eat();
  if (a instanceof Cat)// instanceof:用于判断对象的具体类型。只能用于引用数据类型判断
        // 通常在向下转型前用于健壮性的判断。
  {
   Cat c = (Cat) a;
   c.catchMouse();
  } else if (a instanceof Dog) {
   Dog d = (Dog) a;
   d.lookHome();
  } else {

  }
   }
  }
  打印的结果:
  吃鱼
  吃鱼
  抓老鼠
  啃骨头
  看家

9 内部类

  内部类访问特点:
  1,内部类可以直接访问外部类中的成员。
  2,外部类要访问内部类,必须建立内部类的对象。
  一般用于类的设计。
  分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。
  这时就是还有的事物定义成内部类来描述。
  内部类能直接访问外部类中成员,是因为内部类持有了外部类的引用,即外部类名.this。
  内部类也可以存放在局部位置上,但是内部类在局部位置上只能访问局部中被final修饰的局部变量。
  主要说下匿名内部类:
  顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。
  当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。匿名内部类的声明格式如下:
  new ParentName(){
   ...// 内部类的定义
  }[1]
  匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,
  使用匿名内部类是比较合适的:
  只用到类的一个实例 。
 


 

  

  

  

  





0 0