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. 每次创建对象的时候,都会执行一次。且先于构造器执行。

  • 相关阅读:
    Eclipse 导入项目乱码问题(中文乱码)
    sql中视图视图的作用
    Java基础-super关键字与this关键字
    Android LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot)的参数理解
    Android View和ViewGroup
    工厂方法模式(java 设计模式)
    设计模式(java) 单例模式 单例类
    eclipse乱码解决方法
    No resource found that matches the given name 'Theme.AppCompat.Light 的完美解决方案
    【转】使用 Eclipse 调试 Java 程序的 10 个技巧
  • 原文地址:https://www.cnblogs.com/deityjian/p/11409334.html
Copyright © 2011-2022 走看看