zoukankan      html  css  js  c++  java
  • Java类和对象

    了解类和对象前,简单提及面向对象程序设计。面向对象程序设计就是通过对象来进行程序设计,对象表示一个可以明确标识的实体。例如:一个人、一本书、一个学校或一台电脑等等。每个对象都有自己独特的标识、状态和行为。

    对象的状态(特征或属性,即实例变量),由该对象的数据域来表示。 例如:一个人可以具有名字、年龄、身高、体重、家庭地址等等属性,这些就是“人这个对象的数据域”。

    对象的行为(对象执行的动作,即功能),由方法来定义。例如:定义getName()来获取姓名, getHeight()获取身高,setAddress(String addr)修改地址。

    类和对象的关系

    类是一种抽象的概念集合,是最基础的组织单位,作为对象的模板、合约或蓝图。

    类是对象的类型,使用一个通用类可以定义同一类型的对象,类中定义对象的数据域是什么以及方法是做什么的。 对象是类的实例,一个类可以拥有多个实例,创建实例的过程叫做实例化。实例也称为对象,两者说法一致。

    构造方法

    构造 器 的特征
    它具有与类相同的名称
    它不声明返回值类型。(与声明为void不同)
    不能被static、final、synchronized、abstract、native修饰,不能有return语句返回值

    构造 器 的作用: 创建对象;给对象进行初始化
    如:Order o = new Order(); Person p = new Person(“Peter”,15);

    根据参数不同,构造器可以分为如下两类:
     隐式无参构造器(系统 默认 提供)
     显 式 定义一个或多个 构造器(无参、有参)

      //只初始化名字和性别
        public Person(String name, int sex) {
            this.name = name;
            this.sex = sex;
        }
      
        public Person(String name, int sex, int age, String birthplace) {
            this(name, sex); //使用this()来调用类中的构造器
            this.age = age;
            this.birthplace = birthplace;
        }

    除了定义有参构造方法,也可以定义无参构造方法: public Person(){}。若一个类中没有定义任何构造方法,那么在类中会隐式存在一个方法体为空的无参构造方法,也叫默认构造方法。如果显式的定义构造方法,则默认构造方法失效。

    引用变量访问对象和调用数据域和方法

    对象是通过对象类型变量来访问,该变量包含了对对象的引用。对象类型变量使用操作符(.)来 访问对象数据和方法。 

    创建的对象会在内存中分配空间, 然后通过引用变量来访问。 包含一个引用地址的变量就是引用变量, 即引用类型。 Java中,除了基本类型外,就是引用类型(对象)。

    声明对象类型变量的两种形式

    Fruit f ; //只声明,未指向一个引用地址
    Fruit f = null; //f指向一个空地址
    //两者基本无区别,null是引用类型的默认值

    本质上来看,类是一种自定义类型,是一种引用类型,所以该类类型的变量可以引用该类的一个实例。 

    Fruit f = new Fruit("西瓜", "“甜味”)
    
    //表示创建一个Fruit对象,并返回该对象的引用,赋给Fruit类型的f变量。  变量f包含了一个Fruit对象的引用地址。 但通常情况下,直接称变量f为Fruit对象。

    引用类型变量和基本类型变量的区别

    每一个变量都代表一个存储值的内存位置。 声明变量时,就是告知编译器该变量可以存储什么类型的值。对基本类型变量来说,对应内存所存储的值就是基本类型值。而对于引用类型变量来说,对应内存所存储的值是一个引用,指向对象在内存中的位置。

    除了基本类型,就是引用类型,引用类型包含对象引用,可以将引用类型看作对象。

            int a = 6;
            int b = a; //将a的实际值赋给b        
            TestReferance tr = new TestReferance();
            TestReferance t2 = tr; //将tr的引用赋给t2 , tr和t2指向同一对象
            t2.a = 10; 
            System.out.println(tr.a); // 10

    所以,将引用类型变量赋值给另一个同类型引用变量,两者会指向同一个对象,而不是独立的对象。 如果想要指向一个具有同样内容,但不是同一个对象,可以使用clone()方法。

    【技巧】:如果不再需要某个对象时,也就是不引用该对象,可以将引用类型变量赋值null,表示引用为空。 若创建的对象没有被任何变量所引用,JVM会自动回收它所占的空间。

            TestReferance t1 = new TestReferance(); 
            t1 = new TestReferance(); //t1指向一个新的对象。 t1原来指向的对象会被回收
            //创建一个匿名对象,执行完构造方法后,就会被回收。
            new TestReferance();

    PS:关于NullPointerException异常,一般都是因为操作的引用类型变量指向null,所以对引用类型变量操作时,最好先判断一下是否为null。

    静态与实例的区别

    上面的类中定义的都是实例变量和实例方法,这些数据域和方法属于类的某个特定实例,只有创建该类的实例后,才可以访问对象的数据域和方法。

    静态变量和方法属于类本身,静态变量被类中的所有对象共享,在静态方法中不能直接访问实例变量和调用实例方法。

    public class Test {
        public int a = 5;
        public static int staB = 10; 
        public Test(int a) { this.a = a; }
        public static void main(String[] args) {
            Test t1 = new Test(6);
            Test t2 = new Test(8);
            System.out.println(t1.a + " " + t2.a); // 6  8, 两个对象互不相关 
            t1.staB = 15; //t1对象修改静态变量 staB
            System.out.println(t2.staB); //影响t2对象
        }
    }
    public class Test {
        public int a = 5; //实例变量
        public static int staB = 10; //静态变量
        public Test(int a) { this.a = a; }
        
        public static void staMethod() {
            System.out.println(a); //error, 不允许直接访问实例变量
            insMethod(); //不允许直接调用实例方法
            
            //通过对象来调用
            System.out.println(new Test(5).a);
            new Test(5).insMethod();
            
        }
        //实例方法中,可直接访问静态变量和调用静态方法
        public void insMethod() {
            staMethod();
            System.out.println(staB);
        }
    }

    因为静态变量将变量值存储在一个公共地址,被该类的所有对象共享,当某个对象对其修改时,会影响到其他对象。而实例的实例变量则是存储在不同的内存位置中,不会相互影响。

    访问静态变量和静态方法时,可以不用创建对象,通过“类名.静态变量/静态方法”来访问调用。 虽然能通过对象来访问静态变量和方法,但为了可读性,方便分辨静态变量,应该通过类名来调用。

    this关键字的使用

    关键字this表示当前对象,引用对象自身。 可以用于访问实例的数据域, 尤其是实例变量和局部变量同名时,进行分辨。除此之外,可以在构造方法内部调用同一个类的其他构造方法。

    public int a;
        public String str;
        //不使用this来初始化构造方法
        public TestThis(int a, String str) {
            //隐式存在于每个构造方法的第一行
            super(); 
            a = a;   //指向同名局部变量形参a
            str = str; //指向同名局部变量形参str
        }

    形参名和全局变量同名,但形参是局部变量,所以在方法中优先使用局部变量,这里的赋值是赋值给形参了。解决这个问题,可以修改形参名,但形参名和要初始化的变量名不相等容易引起歧义。

    引用参数传递给方法

    方法是一种功能集合,表明可以做什么,封装了实现功能的代码,要实现某个功能只需要调用相关方法即可,无需关注功能实现细节。大部分方法都需要传递参数来实现相关功能,但是传递基本类型和传递引用类型有什么区别呢?

    给方法传递一个对象参数,实际上是将对象的引用传递给方法。

    public class TestThis {
        public static void main(String[] args) {
            int[] arr = {1, 2};
            swap(arr[0], arr[1]);
            System.out.println(Arrays.toString(arr)); //[1, 2]
            swap(arr);
            System.out.println(Arrays.toString(arr)); //[2, 1]
            
        }
        public static void swap(int a, int b) {
            int temp = a;
            a = b;
            b = temp;
        }
        public static void swap(int[] a) {
            int temp = a[0];
            a[0] = a[1];
            a[1] = temp;
        }
    }

    第一个swap()方法,接收基本类型参数,所以通过访问下标获取数组元素传递给形参,相当于赋一个实际值给形参,所以对形参交换,不会影响实际参数。

    第二个swap()接收一个int类型数组, 数组也是一个对象, 所以此时形参a包含一个该数组的引用,在方法内部对a数组操作,会影响实际参数 arr。 

    上面方法中使用到了方法重载,方法重载就是使用同样的名字,但根据方法签名来定义多个方法。

    方法重载只与方法签名有关,和修饰符以及返回类型无关。被重载的方法必须有不同的参数列表或者参数类型不同。

    参数列表不同必然重载,若参数列表相同,但类型相近时,会引发匹配歧义,因为类型不明确。

         //因为double类型可以匹配int类型,所以会导致编译器匹配歧义
         public static void sum(int a, double b) { }
         public static void sum(double a, int b) { }

    静态代码块:用static 修饰的代码块

    1. 可以有输出语句。
    2. 可以对类的属性、类的声明进行初始化操作。
    3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
    4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
    5. 静态代码块的执行要先于非静态代码块。
    6. 静态代码块随着类的加载而加载,且只执行一次。

    非静态代码块:没有static 修饰的代码块

    1. 可以有输出语句。
    2. 可以对类的属性、类的声明进行初始化操作。
    3. 除了调用非静态的结构外,还可以调用静态的变量或方法。
    4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
    5. 每次创建对象的时候,都会执行一次。且先于构造器执行。

  • 相关阅读:
    Linux操作系统学习之第三篇
    Linux操作系统学习之第二篇
    简介VMware workstaion
    Linux操作系统学习之起始篇
    c# 与java对应的 aes加密(带向量的)
    string转DateTime
    webapi项目创建
    c# mqtt 服务端、客户端简易例子
    vs快捷键
    c# 用byte数组生成图片
  • 原文地址:https://www.cnblogs.com/deityjian/p/11409334.html
Copyright © 2011-2022 走看看