zoukankan      html  css  js  c++  java
  • JAVA类与对象

    1,类的定义
    描述实体的抽象概念,属性及行为相似的对象可以归成一个类。
    在软件中,类就是一个模板,它定义了通用于一个特定种类的所有对象的状态(变量)和行为(方法)。 类是创建对象的模板,对象是类的实例。
     
    声明形式

      [public] [abstract | final] class 类名称

        [extends 父类名称]

        [implements 接口名称列表]

     

            数据成员声明及初始化;

           方法成员声明及方法体;

      }

    关键字
    class: 表明其后声明的是一个类。
    extends: 如果所声明的类是从某一父类派生而来,那么,父类的名字应写在 extends 之后
    implements: 如果所声明的类要实现某些接口,那么,接口的名字应写在 implements 之后
    类修饰符
    可以有多个,用来限定类的使用方式
    public: 表明此类为公有类
    abstract: 指明此类为抽象类
    final: 指明此类为终结类  
    类声明体
    数据成员声明及初始化
    可以有多个
    方法成员声明及方法体
    可以有多个
    数据成员
    表示 Java 类的状态
    声明数据成员必须给出变量名及其所属的类型,同时还可以指定其他特性
    在一个类中成员变量名是唯一的
    数据成员的类型可以是 Java 中任意的数据类型( 基本 类型,类,接口,数组)
    方法成员
    定义类的行为
    一个对象能够做的事情
    我们能够从一个对象取得的信息
    可以没有,也可以有多个;
    分为实例方法和类方法 ( 静态方法 )
     

    类成员的访问控制

    public
    这些成员能被所有的类访问
    protected
    这些成员只能被类本身, 派生类或者同一个包下的类访问。
    private
    这些成员除了类本身外任何类不允许访问。
    default
    不加任何访问控制保留字,这些成员只能被 类本身或同一个包下的类访问。
     

    2,类的特殊成员

    构造方法
    构造方法的名字和类名相同,并且没有返回值(连 void 都不允许)。
    构造方法主要用于为类的对象定义初始化状态。
    我们不能直接调用构造方法,必须通过 new 关键字来自动调用,从而创建类的实例。
    Java 的类都要求有构造方法,如果没有定义构造方法, Java 编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。
    静态数据成员
    静态成员以 static 关键字修饰,如:
    Class Person{

      staticint name

      public static void getName(){……}

    }

    静态方法和静态变量是属于某一个类,而不属于类的对象,不管对象有多少,静态成员在内存中只存在一份拷贝,所有对象共享同一份静态成员。
    静态方法和静态变量的引用可以直接通过类名引用,而不需要经过类的实例化。如: Person.name;  Person.getName ();
    在静态方法中不能调用非静态的方法和引用非静态的成员变量。反之,则可以。
     
    final 数据成员
    final 数据成员类似于 C++ 中的 const 数据,以及 C 中宏定义。
    final 数据成员一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变,但引用变量所指向的对象中的内容还是可以改变的。
     
    final 方法成员
    派生类只能从父类继承 final 方法,但是不能覆盖该 final 方法。
    当一个方法提供的功能已经满足要求,不需要再进行扩展,或者不想被子类覆盖时,可以将方法声明为 final

    抽象方法和抽象类

    在类中没有方法体的方法,就是抽象方法。
    含有抽象方法的类,即为抽象类。
    如果一个子类没有实现抽象基类中所有的抽象方法,则子类也成为一个抽象类。
    我们可以将一个没有任何抽象方法的类声明为 abstract ,避免由这个类产生任何的对象。

    构造方法、静态方法、私有方法、final方法不能被声明为抽象的方法

    3,面向对象的概念

    设计一个窗口

    面向过程:

           在一个结构体中定义窗口的大小,位置,颜色,背景等属性,对窗口操作的函数与窗口本身的定义没有任何关系,如HideWindow,MoveWindow这些函数都需要接受一个代表被操作的窗口参数,这可以理解为,谓语与宾语的关系。

    面向对象:

         定义窗口时,除了要指定在窗口的属性,如大小,位置,颜色等等之外,还要指定该窗口可能具有的动作,如隐藏,移动等。这些函数被调用时,都是以某个窗口要隐藏,某个窗口要移动的格式来使用,可以理解为主语与谓语的关系。

    面向对象的三大特征

    封装
    封装是把过程和数据组织起来,对数据的访问只能通过已定义的方法。
    封装的目的在于将对象的使用者和设计者分开,使用者不必知道行为实现的细节,只需使用设计者提供的消息来访问对象
     
    继承
    新的类可以获得已有类(称为超类、基类或父类)的属性和行为,称新类为已有类的派生类(也称为子类)。

    继承可以增加代码的重用性,在拥有父类的功能基础上增加自己的功能。

    多态
    发送消息给某个对象,让该对象自行决定响应何种行为。 可以理解为横向上的重载,纵向上的覆盖。
    使语言具有灵活、抽象、行为共享、代码共享的优势,很好地解决了应用程序方法同名问题
     
    重载 (Overload)

      BaseClass base = newBaseClass();

      int temp = 1;

      base.fun();   //不带参数

      base.fun(temp);  //int型参数

    覆盖 (Override)

    DerivedC derived=newDerivedC();   //Derived继承于BaseClass.
    BaseClassbase= derived;
    base.play(); //执行的是DerivedC中定义的play().

    类的申明

    public class Window{

      int size;

      private int position[2];

      protected int color;

      public void setSize(intnewSize){

       size = newSize;

      }

      protected void setPosition(int x,int y){

      position[0] = x;

      position[1] = y;

      }

      private void setColor(intnewcolor){

      color = newColor;

      }

      ……

    }
     
    类的实例
    类并不会执行任何功能,而是由类创建的对象实例去完成某些功能。
    对象的创建
    Person per = new Person( );
     Person per;  per = new Person();
    每个对象都必须经过关键字 new 分配内存空间后方能使用。
    数据成员的调用
    per.name=“Li”;
    per.tell ();

    4,所有对象都是引用

    C++ 有两种方式操纵对象
    1. 以标识符直接标识对象 ;

      Person per = Person();

      per.say();

    2. 通过指针以标识符间接标识对象。

      Person *per = new Person();

      per->say();

    Java 只有一种方式操纵对象
    所有对象标识均是对象引用。

    引用VS指针

    引用类似于指针,但是引用没有指针的语义。
    指针支持算术运算,允许前后随意移动。也正因为这样,导致指针存在诸多不安全性。
    引用只能通过赋值指称新的对象,不允许算术运算。可以将引用理解为更安全的指针。
     
    所谓引用数据类型,实际上传递的就是堆内存的使用权,可以同时为一个堆内存空间定义多个栈内存的引用操作。
    public class Person{
    String name;
    int age;
    public void tell(){
    System.out.println ( “姓名 : +name+ “年龄 : +age);
    }
     
    public class Example{

      public static void main(String args[]){

      Person per1=null;

      Person per2=null;

     

      per1=new Person();

      per2=new Person();

     

      per1.name=“张三”;

      per1.age=30;

      per2.name=“李四”;

      per2.age=33;

      per2=per1;       

      per2.age=25;

      per1.tell();        //输出什么?    姓名:张三 年龄:25

      }

    }
     
    对象的内存分配
    对象保存在栈内存中,数据成员保存在堆内存中。每个对象在内存里都有自己的一份数据拷贝。
    方法成员保存在代码区,在内存中只有一份拷贝,同一个类的所有对象共享同一段程序代码。
    思考:对象共享同一段程序代码,如何区分不同对象的数据?
    this 变量代表对象本身。 每一个方法成员内部都有一个 this 引用变量,指向当前的对象。 每当调用一个实例方法时, this 变量将被设置成引用该实例方法的特定的类对象, Java 编译器会将该变量传递到实例方法。方法的代码接着可以与 this 所代表的对象的特定数据建立关联。
     
    5,对象复制:深复制与浅复制
    1,什么时候需要用到对象复制?
    状态复制
    显示的赋值
       直接将一个对象的状态复制到另一个对象
    对象初始化
    用一个现有对象的状态确定一个新建对象的状态
    制作副本
    对象作为方法的参数
    对象按值调用。
    对象作为返回值
    将方法中的局部对象复制一份并返回
     
    JAVA的对象传递
    Java 中,对象作为参数的传递效果总是按引用传递。只有对象引用的复制,不会发生对象实例的复制。
    优点:高效(无需制作副本)
    缺点:不安全(方法调用有副作用)
    final 修改对象参数,仍无法改正以上缺点,因为这样仅仅保证了对象引用没有副作用,对象实例仍可能被改变。
    解决方法:在方法里复制对象,达到按值传递对象的效果。
    优点:安全
    缺点:低效(需要制作副本,更多的手工编程)
     
    2,深复制与浅复制的区别
    复合对象:对象中还包含了其他对象的引用。
    深浅复制只对复合对象才有意义,对普通对象来说效果一样。
    对复合对象,深浅复制的区别:
    浅复制:仅复制复合对象的根对象——只复制了对象引用,不复制对象实例
    深复制:复制复合对象的整个结构——深复制递归复制复合对象中的每个子对象
     
    深浅复制实例 —— 实现 Cloneable 接口
    Object 类是所有类的基类,所有的类都继承自 Object 类。
    Object 类里定义的 clone() 方法采用的是浅复制策略。
    public class Teacher{

      String name;

      int age;

      public Teacher(String name, int age){

           This.name = name;

           This.age = age;

      }

    }
     
    public class student implements Cloneable {

      String name;

      Teacher teacher;

      public student(String name, Teacher teacher){

            this.name=name;

            this.teacher=teacher;

      }

      public Object clone(){

            Student stu=null;

            try{

                  stu=(Student)super.clone();

             }catch(CloneNotSupportedException e){

                  System.out.println(e.toString());

             }

              //stu.teacher=(Teacher)teacher.clone();

              return stu;

      }

    }
     

    Teacher teacher = new Teacher(“张三30);

    Student stu1 = new Student(“小明teacher);

    Student stu2 = (Student)stu1.clone();

    stu2.teacher.name=“李四”;

    stu2.teacher.age = 32;

    System.out.println(stu1.name+“老师信息:”+stu1.teacher.name+“ ”+stu1.teacher.age );

    //输出结果是?

    小明老师信息:李四 32

    深复制

    修改 Teacher 类(父类),为 Teacher 类重定义 clone 方法。
    public class Teacher inplements Cloneable {

      String name;

      int age;

      public Teacher(String name, int age){

      This.name = name;

      This.age = age;

      }

      public Object clone(){

      Teacher teacher=null;

       try{

            teacher=(Teacher)super.clone();

      }catch(CloneNotSupportedException e){

            System.out.println(e.toString());

      }

      //this.name = new String(teacher.name);

      return teacher;

      }

    }
  • 相关阅读:
    深度学习100问之深度学习的本质
    Docker在Windows下的安装以及Hello World
    杂谈——如何在CSDN上上传图片,并添加到自定义栏目中
    打造livecd的注意事项
    打造livecd的注意事项
    磁盘管理基础
    磁盘管理基础
    磁盘管理基础
    磁盘管理基础
    LFS资料和SSH远程登录全过程
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2993678.html
Copyright © 2011-2022 走看看