本文最后更新于:1 年前

Java笔记——对象、类

创建时间:2019.11.11

说明:持续更新ing


  1. 对象的概念。
  • 对象:对象是类的一个实例(实实在在存在的个体),有属性(状态)行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。

    属性(property): 静态特征
    行为(behavior): 动态特征

  • :类是对现实生活中事物的描述。类是一个模板,它描述一类对象的行为和状态。同种类型对象共性的抽象

  • 用老师的话来说,就是下面这样——>
    image.png

  • 下图中男孩(boy)女孩(girl)类(class),而具体的每个人为该类的对象(object)
    菜鸟教程.png


  1. 【定义类】

image-20191116135106458


  • Java中的类
    类可以看成是创建Java对象的模板。
    通过下面一个简单的类来理解下Java中类的定义:
public class Student {
    int id; 
    String name; 
    double score1, score2, score3; 
    public Student(int id, String name) {
        this.id = id; 
        this.name = name; 
    }
    public double getAverageScore() { 
        return (score1 + score2 + score3) / 3; 
    } 
}

一个类可以包含以下类型变量:

局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
类变量:类变量也声明在类中,方法体之外,但必须声明为static类型。
一个类可以拥有多个方法。

  • Java中的对象
    现在让我们深入了解什么是对象。看看周围真实的世界,会发现身边有很多对象,车,狗,人等等。所有这些对象都有自己的状态和行为。
    拿一条狗来举例,它的状态有:名字、品种、颜色,行为有:叫、摇尾巴和跑。
    对比现实对象和软件对象,它们之间十分相似。

软件对象也有状态和行为。软件对象的状态就是属性,行为通过方法体现。
在软件开发中,方法操作对象内部状态的改变,对象的相互调用也是通过方法来完成。

  • 创建对象——>

    /*有两种基本形式*/
    
    /*1.对象声明和创建*/
    类名 对象名 = new 类名();
    Student xiaoming = new Student ();
    
    /*2.先声明,后创建*/
    类名 对象名; // 类(对象)变量
    对象名 = new 类名(); //实例化
    Student xiaobai ;
    xiaobai = new Student();
  • java对象内存映射像示意.png

  • image.png


  1. 类和对象的关系:类是具有相同==属性和方法==的集合,是对对象的抽象描述。
  • 现实生活中的对象:张三、李四。

  • 【想要描述】提取对象中的共性内容。对具体的抽象。

  • 【描述时】这些对象的共性有:姓名、学号、年龄、性别、学习Java等等。(即定义类:描述事物的属性和行为,就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量和成员方法)。

  • 映射到Java中,描述就是class定义的类,具体对象就是new建立的实体

  • 这些描述在Java当中是用类的形式来体现的。而对象是通过Java的new操作符所产生的一个实体,这个的实体存在于==堆内存==当中。

    image.png
    //定义类,就是描述事物,就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量和成员方法)。
    //需求:描述车汽车(颜色,轮胎数)。
    class	Car {
        //描述颜色
        String color = "red";
        //描述轮胎数
        int num = 4;
        //运行行为。
        void run() {
            System.out.println(color+".."+num);
        }
    }
    
    class	CarDemo {
        public static void main(String[] args){
            //生产汽车:在Java中通过new操作符来完成。
            //其实就是在堆内存中产生一个实体。
            Car c = new Car();	//c就是一个【类类型】变量。记住:类类型变量只想对象。
            //需求:将已有车的颜色的颜色改成蓝色。指定该对象做使用。
            //在Java指挥方式是:【对象.对象成员】
            c.color = "blue";
            //需求:想要车运行起来。
            c.run();
        }
    }

Car c = new Car();在内存中的示意图——>

image.png

c.run();——>输出这个车的颜色“蓝色”和轮胎数“4”。

(1)倘若在c.run();后加入Car c1=new Car();c1.run();——>

image.png

(2)若main的代码块改为:

class	CarDemo {
    public static void main(String[] args){
		Car c = new Car();
		c.num = 5;
		Car c1 = c;
		c1.color = "green";
		c.run();
    }
}

在内存中的示意图——>

image-20191113105054592

对对象调用的基本概念:用new建立对象,在堆内存中产生对象。那么对象的特点在于封装数据,数据包含属性和行为。想要操作对象中的内容就指挥对象做事,指挥哪个对象要明确,操作什么也要明确,用对象.xyz的形式就能完成。

【注意】:
如下图,

image.png

以前定义在函数里面,现在定义在函数外面


  1. 【方法】
    方法的定义:

    • 方法是类或对象的行为特征的抽象。

    • Java中的方法不能独立存在,所有的方法必须定义在类中。

    • 使用 “类名.方法” 或 “对象.方法” 的形式调用。

    • 语法格式:

      权限修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2,...) {
      	// 方法体
      	方法语句序列//当返回类型非void时,最后一条被执行语句必须是return语句,返回对应类型的值
      }

      访问权限/权限修饰符(4P权限):

      访问权限 类内 包层内 子类 包层外
      public
      protected ×
      package (缺省) × ×
      private × × ×

      return语句:

    • 结束方法调用,并返回值。

    • return 表达式; return;
      🔺方法被调用时,执行到方法内的return语句,则不论方法里是否还有语句未执行,立即结束方法的调用,并将return 后的表达式的值返回方法调用者
      🔺利用return 语句返回值,仅能返回一个值
      🔺return语句仅结束方法的执行
      🔺void型方法

      方法分类:

    • 无参数无返回值

    • 有参数无返回值

    • 无参数有返回值

    • 有参数有返回值

      public class Method {
          
          public void aMethod() {
              System.out.println("无参数无返回值的方法");
          }
          
          public void bMethod(int b) {
              System.out.println("有参数无返回值的方法");
          }
          
          public int cMethod() {
              System.out.println("无参数有返回值的方法");
              return 10;
          }
         
          public int dMethod(int d) {
             System.out.println("有参数有返回值的方法");
              return d;
         }
      
         public static void main(String[] args) {
              int ret;     // 创建Method类的对象
             Method md = new Method();     // 通过对象.方法调用
              md.aMethod();
             md.bMethod(10);
              ret = md.cMethod();
             ret = md.dMethod(10);
              System.out.println(ret);
         }
      }

      方法的参数:

    • 方法可以没有参数,或者有多个参数,参数类型可以是任意类型

    • 方法参数也是局部变量

      参数为引用数据类型4时:

    • 当对象实例作为参数传递给方法时,传递的是对象的引用,为地址传递,接受参数的方法可以改变参数的值。

      参数为简单数据类型时:

    • 传递的是参数的副本,为值传递,接受参数的方法中不会改变参数的值。

      public class MethodParam {
          
          /** 
           * 方法的参数为基本数据类型时,传递的是值的副本(值拷贝)
           * 方法中不会改变元参数的值
           */
          public void swap(int a, int b) {//a, b为形参
              int tmp;
              tmp = a;
              a = b;
              b = tmp;
          }
          
          int x = 100, y = 200;
          
          /**
           * 方法的参数为引用数据类型时,传递的对象的引用(传地址)
           * 方法中可以改变参数的值
           */
          public void swap2(MethodParam mp) {
              int tmp = mp.x;
              mp.x = mp.y;
              mp.y = tmp;
          }
      
          public static void main(String[] args) {
              MethodParam mp = new MethodParam();
              
              int m = 10, n = 20;
              System.out.println("交换前:a = "+m+",b = "+n);
              mp.swap(m, n);// m,n为实参
              System.out.println("交换后:a = "+m+",b = "+n);
              
              System.out.println("交换前:x = "+mp.x+",y = "+mp.y);
              mp.swap2(mp);
              System.out.println("交换后:x = "+mp.x+",y = "+mp.y);
          }
      
      }

      普通方法调用——>

      image.png

      成员方法和成员变量的关系——>

      image.png


  1. 【成员方法】和【构造方法】

    【成员方法】

——————————————————————————— 我 是 分 割 线 ————————————————————————————

【构造方法】

构造方法需满足以下三个条件 :
  • 1、方法名与类名同名

  • 2、在方法中不能使用 return 语句,即无返回值

  • 3、在方法名的前面*没有返回值的类型声明 *
    (有看到“ 构造方法无返回值也不可以加void,但其实返回的是首地址 ”这话还得去证实,先放在这里)

  • image.png

  • ==老师推荐==:显式无参构造子,作为一种良好实践,定义了其他构造子,那就准备一个无参构造子

package me;
public  class Me {
    private  String name; //成员变量
    public Me(String name){ //构造方法
        this.name = name;
    }
    public String getName() { //成员方法
        return name;
    }
    public void setName(String name) {//成员方法
        this.name = name;
    }
}

我如果我在添加一age 如下 添加方法依然是成员方法 ,

package me;
public  class Me {
    private  String name; //成员变量
    private String age; //成员变量
    public Me(String name){ //构造方法
        this.name = name;
    }
    public String getName() { //成员方法
        return name;
    }
    public void setName(String name) {//成员方法
        this.name = name;
    }
    public String getAge() {//成员方法
        return age;
    }
    public void setAge(String age) {//成员方法
        this.age = age;
    }
}

个人理解:无论多少方法,==除了构造方法外,其余都是成员方法==,当然这样理解可能有点偏见..

它们的区别:

  • 构造方法一般是给对象的数据进行初始化,没有返回值

  • 成员方法一般实现对类中成员变量的操作,提供某些功能,有返回类型,可以为void类型

成员方法与构造方法调用的区别

package me;
public class Book {    
    public static void main(String[] args) {        
        Me me = new Me("张三");//构造方法调用    
        System.out.println(me);         
        me.setName("李四");//成员方法调用       
        System.out.println(me.getName());     
    }
}

从上面的demo中可以看出,==构造方法通过new运算符调用====成员方法通过对象调用==

注意:类中除了构造方法以外的方法都是成员方法。原因是在类中,除了变量外的基本都是成员方法。

——————————————————————————— 我 是 分 割 线 ————————————————————————————

【this 关键字】

https://i.loli.net/2019/11/16/49d7AMODXhKbsuy.png

——————————————————————————— 我 是 分 割 线 ————————————————————————————

【重载构造方法之间的调用】

image.png

image.png

【含对象成员的构造方法调用】image.png

image.png

【无继承情况下的对象初始化顺序】image.png


  1. 【创建对象】

对象是根据类创建的。在Java中,使用关键字new

  • 声明:声明一个对象,包括对象名称和对象类型。
  • 实例化:使用关键字new来创建一个对象。
  • 初始化:使用new创建对象时,会调用构造方法初始化对象。

下面是一个创建对象的例子:

public class Puppy{   
    public Puppy(String name){      
        //这个构造器仅有一个参数:name      
        System.out.println("小狗的名字是 : " + name );    
    }   
    public static void main(String[] args){      
        // 下面的语句将创建一个Puppy对象      
        Puppy myPuppy = new Puppy( "tommy" );   
    } 
}

编译并运行上面的程序,会打印出下面的结果:

小狗的名字是 : tommy

——————————————————————————— 我 是 分 割 线 ————————————————————————————

【访问实例变量和方法】

通过已创建的对象来访问成员变量和成员方法,如下所示:

/* 实例化对象 */ 
Object referenceVariable = new Constructor(); 
/* 访问类中的变量 */ 
referenceVariable.variableName; 
/* 访问类中的方法 */ 
referenceVariable.methodName();

——————————————————————————— 我 是 分 割 线 ————————————————————————————

【访问实例变量】和【调用成员方法】:

public class Puppy{   
    int puppyAge;   
    public Puppy(String name){      
        // 这个构造器仅有一个参数:name      
        System.out.println("小狗的名字是 : " + name );    
    }    
    public void setAge( int age ){       
        puppyAge = age;   
    }    
    public int getAge( ){       
        System.out.println("小狗的年龄为 : " + puppyAge );        			return puppyAge;   
    }   
    public static void main(String[] args){     
        /* 创建对象 */      
        Puppy myPuppy = new Puppy( "tommy" );      
        /* 通过方法来设定age */    
        myPuppy.setAge( 2 );      
        /* 调用另一个方法获取age */    
        myPuppy.getAge( );     
        /*你也可以像下面这样访问成员变量 */   
        System.out.println("变量值 : " + myPuppy.puppyAge );   
    } 
}

编译并运行上面的程序,产生如下结果:

小狗的名字是 : tommy
小狗的年龄为 : 2
变量值 : 2

  1. 【方法重载,重构,覆盖,重写的区别】

    方法重载还是比较好理解的,就是在类的内部,定义多个方法,这些方法的方法名字相同,参数类型、参数顺序、参数个数不同,注意,返回值类型并不能区分重载 。

public void show(int a,double b){

}
public void show(double c){

} 
public int show(double d){
    return  1;
}   //报错,方法已经定义了

方法重写(override)
方法重写和方法覆盖都是一个道理,发生在子类继承父类或者实现接口的类,要求的是:

1.方法名字相同,
2.参数个数不同,
3.返回值类型不同 ,

代码:

image.png image.png

方法重构

定义:在不改变外界外界访问的情况下对代码进行修改,但是不改变原方法的效果,提高其性能,使程序更加易读,可维护。
重构是在不改变软件可观察行为的前提下改善其内部结构
重构通常不是一次性的,它贯穿软件的整个生命周期,只要觉得不合理都是重构的时机。


题目:下面说法中,错误的有( )

​ A. Java面向对象语言容许单独的过程与函数存在;

​ B. Java面向对象语言容许单独的方法存在;

​ C. Java语言中的方法属于类中的成员(member);

​ D. Java语言中的方法必定隶属于某一类(对象),调用方法与过程或函数相同。

答案:ABC

解释:

方法与函数:这两个概念不严格区分,就是一个东西,通过对象调用的,就是方法,直接调用,就是函数;

在java中,everything is object 所以,方法,函数,必须隶属于某一个类或对象, java中没有过程。(类中的代码块不知道算不算,就算代码块是过程,也是必须在类中才有的)

对于C选项,方法分为静态方法和非静态方法,静态方法属于类成员,非静态方法属于实例成员。


  • 类其实一种类型,它封装了数据和操作。

  • 对象是类的实例

  • 一个对象比属于某个类

  • 一个类可以声明多个对象


  1. 问:构造方法可以调用本类的其他方法吗?

1,构造方法可以调用本类的其他方法。既然可以调用本类的属性,那么也就可以调用属于本类的其他方法。

2,需要注意的是,如果要在构造方法里调用一个非静态方法时,应该将该方法声明为private。
因为如果这个类被其他类继承成为父类时,这个方法不是private的又被子类所重载,这样在实际创建子类的过程中递归调用到了父类的构造器时,父类构造器对这个方法的调用就会由于多态而实际上调用了子类的方法,当这个子类方法需要用到子类中实例变量1的时候,就会由于变量没有初始化而出现异常(子类中的实例变量没有初始化这种情况还是会遇见的),这是Java不想看到的情况。


  1. 一个类的构造方法有多个,在其他类中是否可以被调用?

只要不是私有的构造函数,在其他类中就可以调用。 传对应的参数就行了 。

class` `A{
  ``public` `A(String s){}
  ``public` `A(``int` `n){}
  ``public` `A(String s, ``int` `n){}
}
class` `B{
  ``A a1 = ``new` `A(``"abc"``);
  ``A a2 = ``new` `A(``1``);
  ``A a3 = ``new` `A(``"aaa"``,``2``);
}

  1. 类是一种引用类型

Java的引用类型只有三种,分别是


  1. 问:方法一定是在类内部被定义的?

所有方法必须写在类体里,也包括构造方法2的。

static方法同样属于类,叫类方法或静态方法,它与类一同被加载时,处于内存的公共代码区中,无需创建实例来调用,只需用类名引用即可。
static方法既可以通过类名来调用,也可以通过类的实例调用。

Java一切都是以类的形式存在,方法是类的一部分,需要通过类才能进行方法的调用。
从内存存储角度来说,java中找对应方法时,都是先找对应类实例,类实例是根据类来初始化内存的。如果方法在类外部,则无法找到该方法。
所以方法必须在类体里。

注意: 可以在其他类里使用这个类的方法(在不同的包下就要引ltem这个类),继承就是一个类从另一个类继承通过关键字extends 来实现


  1. 问:构造方法中可不可以有return语句呢?

(这个解释有问题?)可以。而是我们写成这个样子就OK了:return;
其实,在任何的void类型的方法的最后你都可以写上:return;


  1. 问:非构造方法的一般成员方法必须有return语句?

错。 (待补充……)


  1. 问:类中的数据成员可以按需选择任意类型,包括类本身?

可以。可以参考下图,图源于陈三千的博客

举例.png
  1. 问:Java中构造函数的权限可以是private吗?

可以,这个类就不能再外部被new了,如果需要这个类的实例化对象,就只能在类内部提供静态方法生产这个类的对象了。


  1. 问:构造方法能不能被重载,构造方法能不能被重写?

在回答这两个问题之前,首先先回顾:什么是构造方法?构造方法的特点是什么?

概述:构造方法存在于类中,给对象数据(属性)初始化;

特点:方法名与类名一样;无返回值无void;

默认构造方法:我们不创建一个构造方法时,系统默认提供一个无参构造;当我们创建一个构造方法时,系统不再提供无参构造,所以在实际项目中,全部手动给出无参构造

其次\什么是重载?什么是重写?**

重载:存在于在一个类中,方法名相同,方法参数的类型或个数不同

重写:存在于子父类中,方法名、方法参数、返回值全部相同

所以:构造方法可以重载,不能重写

在一个类中,可以有多个构造方法(方法参数不同) ,即重载,来实现对象属性不同的初始化;

但是子类中不能定义一个方法无void无返回值的方法,编译错误,即子类无法继承构造方法,但是子类的构造器中可以调用父类的构造方法(默认自动调用无参构造)

注意:回答来源于 CSDN博客


  1. Java中可以定义一个空类(即没有数据成员和成员方法) 。

  1. 问: 下面这个类有几个构造方法?
class	A{}

1个。(待补充……)


  1. 问:Java 类可以作为( C )

    A.类型定义机制 B.数据封装机制

    C.类型定义机制和数据封装机制 D.上述都不对


  1. 用于定义类头的修饰符可以是public、abstract、final或者是默认(friendly)

  1. 题目:下列说法错误的有( CD )
      A. 在类方法中可用this来调用本类的类方法
    B. 在类方法中调用本类的类方法时可直接调用
      C. 在类方法中只能调用本类中的类方法
      D. 在类方法中绝对不能调用实例方法

C:类方法可以调用外部其他类的方法。
D:只要实力化对象,也是可以调用实例方法的。


  1. 判断: 只有基本类型的参数传递使用值传递。

错误。

引用类型参数的传递,依然是值传递。但因为是地址值,所以会指向同一个对象实例。


  1. Java中方法的参数传递是值传递(pass by value),并且为单向传递

  1. 《Java 变量参数传入方法,修改后是否影响外面的值》。参考 博客

  1. 《某个变量当作函数的参数传递后,函数内部修改了。到底这个变量是否受影响》。参考 博客

  1. 问:类设计get方法和set方法的作用是什么?

    答1:一般类的成员变量被设置为private(私有的),这样设置安全性比较高,但是设置为私有的后其他的类和对象则无法调用该对象了,所以会有get和set方法,这两个方法一般设置为public,在其他的类中通过对象调用set或get方法即可操作私有的变量,增强程序的安全性,set为给对象赋值的方法,而get则是取得变量值的方法!

    答2:get set常用在自定义类,类创建了一个实例对象后,用set设置对象的某一个属性,get得到对象某一属性。如果不使用get set,你就得用点,点出来还得是个方法。其实就是给get set换个名而已。而且get set作为内部方法,可以访问私有数据

    答3:别说的那么专业化了,理解都要半天。
    就这么理解吧,面向对象中,想对类的成员变量设置访问一些权限,于是,就将该字段设置为private的,这样别的类就不能访问了,然后在该内定义两个方法,一个专门用于获取,一个用于修改,这样,在你不想让别人乱动该字段的时候,就在该方法内写一些限制条件。
    而为了规范起见(团队开发需要嘛),就根据人家老外的习惯,将方法名设置为set+字段名,get+字段名(名字乱改没问题),既然规范了,那就是别人都叫这名了,于是,有些框架给对象赋值就有方法了,方法名称由get或set开始的又有private变量名的,就找出来调用。hibernate1框架就这样弄得,至于后面的版本是不是这样就不大清楚了。
    JavaBean就是一个JAVA类,既然是JAVA类就不需要什么组件了,这玩意直接深入到虚拟机了的

    image.png

    image.png

    image.png

    image.png

    image.png


  1. Java的包装类:

    【包装类的概念】

    image.png

    【Integer类的用法】

    image.png

    image.png

    【自动装箱机制和自动拆箱机制】

    image.png

    image.png


  1. 匿名对象:

使用方法:

  1. 当对对象的方法只调用一次,可以使用匿名对象来完成,这样写比较简化。如果对一个对象进行多个成员调用,必须给这个对象起个名字。
  2. 可以将匿名对象作为实际参数进行传递。











注脚:


 目录