javaSE 类和对象

面向对象设计,其实质上就是对现实世界中的对象进行建模操作。
举个例子:比如一个人a,他有身高,体重,眼睛颜色,头发长短等等这些属性,同时他有奔跑(这个动作)的能力,有跳跃(这个动作)的能力,等等。但一个人b,他也有身高,体重,眼睛颜色,头发长短等等这些属性(属性的值肯和他人不同,比如a的身高180,b的身高170),同时他也有奔跑(这个动作)的行为,有跳跃(这个动作)的行为,等等。然后你发现所有人(人这一类别的生物)都有这些属性和行为。那我们可以将这些整合成一个类,有身高,体重,眼睛颜色,头发长短等等这些属性,同时他有奔跑(这个动作)的行为,有跳跃(这个动作)的行为。而一个具体的人就是这一类的一个对象。而具体的对象之间的属性可能不同。

一·面向对象基本思想

面向对象的程序设计过程是在现实世界的应用域中寻求事物,将同类事物分类,抽象成类,建立对象模型(用类之间的关系表示现实世界中事物之间的联系),在程序编码中,先定义类,再根据类定义对象。
由对象组成系统(用对象表示现实世界中事物,用对象之间的关系表示现实世界中事物之间的联系)
比如,图书管理系统
在这里插入图片描述
在这里插入图片描述

(1)面向对象的基本概念

1、现实世界中的事物
在现实世界中,事物有两大类。①我们身边存在的一切有形事物和抽象概念。②我们身边发生的一切事件。不同的事物具有各自不同的特征和功能。
现实世界中的事物具有如下特征:
① 有一个名字且来惟一标识该对象:
② 有一组状态用来描述其特征;
③ 有一组操作用来实现其功能。
2、类
类是对具有相同属性和相同服务的一组相似事物的抽象。或者说,类所包含属性和服务描述了一组事物的共有的属性和服务。在面向对象的程序中,类是建立某个具体对象时使用的模型或模板。
类具有:① 模块性;②抽象性;③ 继承性。
3、对象
对象是类的一个实例,是对现实世界中事物的抽象,也就是对现实世界中事物的逻辑化。对象是既包括属性(状态)数据,又包括作用于属性数据的一组操作 (行为,方法、服务)的封装体,或者说,对象是属性数据和操作的封装体。对象的属性通过各自的操作可以改变。
现实中,随处可见的一种事物就是对象。对象是事物存在的实体,如人,书,计算机等等。将对象划分成两个部分,既静态部分和动态部分。
静态部分:就是不能动的部分,这个部分称为”属性“,任何对象都会具备其自身的属性
动态部分:一个人,他有身高,体重,性别,年龄,眼睛颜色,头发长短等等这些属性,具有这些属性的人会执行哪些动作,即他的行为,这称之为动态部分。
面向对象思想解决问题:
1.首先从问题中抽象出对象
2.然后识别出这个对象的属性
3.然后识别这个对象的动态行为
4.识别出属性和行为后,这个对象就被定义完成了。然后根据问题定义具体方案

*类和对象的关系相当于类型与变量之间的关系,类是一种数据类型,对象是用类定义且实例化的变量。
4、消息
消息是向某个对象提出执行该对象具有的某个服务的申请。不同对象之间通过发送消息向对方提出服务要求,接受消息的对象主动完成指定服务。
通常,一个消息由以下三部分组成:
① 接受消息的对象;
② 消息名;
③ 零个或若干个参数。
通常消息分为三类:
① 返回对象内部属性(状态)的消息;
② 改变对象内部属性(状态)的消息;
③ 改变系统状态的消息,或产生特定结果的消息。

(2)面向对象的基本特征

1、抽象性
抽象性是对事物的抽象和概括描述,实现了现实世界向计算机世界的转化。面向对象中的类是对现实世界中相同属性和相同服务的一组相似事物的抽象。对象是类的实例化,因而对象是对现实世界中事物的抽象。
2.封装性
封装性是一种信息隐藏技术,其目的是将对象的设计者和对象的使用者分开。对象的封装性体现在:
① 对象具有清楚的边界;对象内部的数据结构和操作限定在这个边界之内。
② 对象向外界提供访问接口。在Java中对象的外部接口是公有(public)数据成员和公有(public)成员方法。
③ 对象的内部实现是不公开的。
3、继承性
类与类之间具有关系,这种关系被称为关联。关联主要描述两个类的一般二元关系。比如,学生类与教师类是一个关联,教师类与学校类是一种关联。两个类之间的关系有很多种,继承是关联的一种。
比如解决信鸽送信的问题时,我们会建立一个鸟类。鸽子属于鸟类,具有与鸟类相同的属性和行为,便可以在创建信鸽类时拿来复用,并且保留鸟类的属性和行为。但是并不是所有鸟类都有送信的习惯,因此还需要再添加一些信鸽具有的独特属性和行为。鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共有的属性和行为。
① 子类自动继承其超类的语义特性
另一个例子,人类、学生类、大学生类的继承关系。
在这里插入图片描述
在这里插入图片描述
② 子类可以从它的多个直接超类中继承它们的语义特性(多重继承性)
如下图所示,在职研究生类、研究生类和教师类的继承关系。
在这里插入图片描述
在java中类不具有多重继承性,但接口具有多重继承性

4.多态性
多态性是指同一个消息被不同类型的对象或相同类型的对象接受时产生不同的行为。
Java中提供两种多态机制:重载、覆盖。

二·类

类是Java程序的基本组成要素,它封装了一类对象的状态和方法。Java源程序中的类分为两种:
① 系统定义的类。
② 用户自定义的类。
类包括两部分:类声明和类体。
类的定义格式

[修师符] class 类名 [extends 父类名] [implents  接口名] {
	类体
}

(1) 类申明

① 修饰符

·abstract
abstract修饰符用来指定所声明的类是抽象类。抽象类是指没有完全实现的类,且这种类不能被实例化,只能作为父类来使用。
抽象类中可以包含抽象方法,也可以包含普通方法。抽象方法需要用abstract修饰,不需要实现

abstract class Animal{
   public abstract void shout();
   public void display(){
     System.out.println("Animal");
   }
}
public class Dog extends Animal{
   public void shout(){
      System.out.println("汪汪......");
   }
   public void display(){
      System.out.println("Dog");
   }
}

·public
public修饰符用来说明一个类是公共类,公共类是指既可以被所属包中的类访问,也可以被其他包中的类访问,因此也称为公共共享类。公共类是一种完全实现的类,可以实例化为对象。

public class Demo{
	//类体
}

·final
使用final修饰符可以声明类是最终类。最终类不能被其他类所继承,即最终类不能有子类。

final class Example{
   //类体
}
下面的类声明是不允许的:
class ChildClass extends Example{
    //类体
}

·default
default即默认,就是不使用任何修饰符。不使用任何修饰符的类可以被同一包内的类访问。

 class Example{
   //类体
}

② extends
在类声明中,使用关键字extends可以指定所声明类的父类。

class Example extends FirstExample{
    //类体
}

在Java语言中,每个类都有父类。如果没有显式指明类的父类,则隐含地把java.lang.Object类作为父类。
在extends后只能指定一个父类,不能指定多个父类
③ implements
用implements指定一个类实现的接口。

interface Animal{
   public void shout();
}
public class Dog implements Animal{
   public void shout(){
       System.out.println("汪汪......");
   }
}

一个类可以实现多个接口,因而在implements可以指定多个接口名,用逗号分隔。

(2) 类体

类体用来指定类的属性和行为,包括两部分:成员变量声明和方法声明及其实现。
一般情况下,类体中的成员变量声明在前,方法声明及其实现在后。
java也允许在一个类的类体部分定义成员类,即内部成员类。
①成员变量
对象的属性也成为成语变量
如,定义一个图书类,成员变量对应对象的属性。

package com.code;  //定义包

public class Book {
    private String name;    //成员变量
    public String getName(){    //定义一个方法
        int id=0;   //局部变量
        setName("java");   //调用类中的其他方法
        return  "id:"+id+" "+"name:"+this.name;   //返回值
    }
    private void setName(String name) {   //定义一个setName方法
        this.name=name;
    }
    public  Book getBook(){   
        return this;      //返回Book类引用
    }
}
package com.code;   //同一包下创建另一个类

public class Test {
    public static void main(String[] args) {
        Book book=new Book();
        System.out.println(book.getName());
        System.out.println(book.getBook());
    }
}

输出结果:
id:0 name:java
com.code.Book@16d3586

② 成员方法
java中使用成员方法对应于类对象的行为。以Book类为例,它包含getName()和setName()两个方法,这两个成员方法分别为获取图书名称和设置图书名称的方法
定义成员方法的语法格式

权限修饰符 返回值类型 方法名(参数类型 参数名){
		//方法体
		return  返回值
}

一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量,同时成员方法有返回值和不返回值得选择。如果方法需要返回值,可以在方法体中使用return关键字,使用这个关键字方法的执行将被终止
返回值可以是计算结果,也可以是其他想要的数值和对象,返回值类型要与方法返回值类型一致
在成员方法中可以调用其他成员方法和类成员变量。
如果一个方法中含有与成员变量同名的局部变量,则方法中对这个变量的访问以局部变量进行。
③ 权限修饰符
权限修饰符主要包括private,public和protected,这些修饰符控制着对类和类成员变量以及成员方法的访问。
如果一个类的成员变量成员方法被修饰为private,则该成员变量只能在本类中被使用,在子类中是不可见的,并且对其他包的类也是不可见的。如果将类的成员变量和成员方法权限设为public,那么本来,子类和其他包的类都可以使用。
如果一个类的访问权限被设置为private,这个类将隐藏其内的所有数据,以免用户直接访问它。
如果一个类使用protected修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法
如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为public访问权限
public和protected修饰符的类可以由子类访问,如果子类和父类不在同一包中,那么只有修饰符为public的类可以被子类进行访问。
如果父类不允许通过继承产生的子类访问它的成员变量,那么必须使用private

访问包位置publicprivateprotected
本类可见可见可见
同包中的其他类或子类可见不可见可见
其他包中的其他类或子类可见不可见不可见

当声明类时不使用public,protected和private修饰符设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以调用这个类的成员变量或成员方法

package com.code;

class Test {
    public void dosomething() {
        //方法体
    }
}

上述代码中,由于类的修饰符为默认修饰符,即只有一个包中的类可以调用这个类的成员变量或成员方法,而Test类中的dosomething()方法的权限设置的是public,即使这样dosomething()方法的访问权限依然与Test类的访问权限相同,
因为java规定,类的权限会约束类成员的权限

 public void dosomething()  等同于  void dosomething()

④局部变量
如果在方法类内定义一个变量,那么这个变量被称为局部变量
或者在某一代码块内定义一个变量,他的作用范围就是这代码块。
局部变量不可在其作用范围内再定义一个与其同名的局部变量
不可在局部变量作用范围外使用局部变量

⑤this关键字
比如上面的例子

 private void setName(String name) {   //定义一个setName方法
        this.name=name;
    }

成员变量与setName()方法中的形式参数相同,都为name。但在使用时到底是用的哪个,java规定使用this关键字来代表本来对象的引用,this关键字被隐式的用于引用对象的成员变量和方法
this.name指的就是Book类中的成员变量name,而 this.name=name中的第二个name指的是形参name
this可以调用成员变量和成员方法,但最常规的调用方法是使用“对象.成员变量”或"对象.成员方法“进行调用
this引用的就是本类的一个对象。在局部变量或方法参数覆盖了成员变量时,就要使用this指明引用的是类成员还是局部变量或方法参数

this除了可以调用成员变量或成员方法之外,还可以作为方法的返回值

public  Book getBook(){   
        return this;      //返回Book类引用
    }

this也可以调用类中的构造方法

(3)类的构造方法

在类中除了成员方法之外,还存在这一种特使类型的方法,那就是构造方法。
构造方法就是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类会自动调用构造方法
构造方法的特点如下:
构造方法没有返回值(不需要使用void)
构造方法的名称要与本来的名称相同

public Book(){
    //构造方法体
}

在构造方法中可以为成员变量赋值,这样实例化一个本来的对象时,相应的成员对象也将被初始化
如果类中没有明确定义构造方法,编译器将自动创建一个不带参数的默认构造方法。如果在类定义了有参数的构造方法,那么编译器将不会创建一个不带参数的默认构造方法。如果调用无参的构造方法,将会报错
this也可以调用类中的构造方法

package com.code;

public class Test {
   public Test(){
       this("this 调用有参构造方法");
       System.out.println("无参构造方法");
   }
   public Test(String name){
       System.out.println("有参构造方法");
   }
}

package com.code;

public class Demo {
    public static void main(String[] args) {
        Test test1=new Test();
        Test test2=new Test("调用有参构造方法");
    }
}
输出结果:
有参构造方法
无参构造方法
有参构造方法

(4)静态变量,常量和方法

static关键字,由static修饰的变量,常量和方法称为静态变量,常量和方法
有时在处理问题时会需要两个类在同一个内存区域共享一个数据。
比如,在球类中使用PI这个常量,本类需要这个常量,在另一个类圆类中也需要使用这个常量。这时没必要再两个类中都去创建PI常量,因为这样系统会将两个不在同一类中定义的常量分配到不同的内存空间。解决这个问题可以将这个常量设为静态的.
被声明为static的变量,常量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类调用静态成员

类名.静态类成员    //注意是类名  不是对象名  比如Demo demo=new Demo();  demo是对象名
                                                                     
package com.code;

public class Demo {
    final static double PI=3.1415;
    static int id;
    public static void method1(){
        System.out.println("method1");
    }
    public void method2(){
        System.out.println(Demo.PI);
        System.out.println(Demo.id);
        Demo.method1();   
    }
}
package com.code;

public class Test2 {
    public static void main(String[] args) {
        Demo demo=new Demo();
        demo.method2();  
    }
}
输出结果:
3.1415
0
method1

当使用静态变量时,直接调用这些静态成员即可。但静态成员同样遵循着public,private,protected修饰符的约束

静态方法中,不可以使用this关键字,不可以调用非静态方法
比如下面的代码编译时会报错

package com.code;

public class Demo {
    final static double PI=3.1415;
    static int id;
    public static void method1(){
        System.out.println("method1");
    }
    public void method2(){
        System.out.println(Demo.PI);
        System.out.println(Demo.id);
        Demo.method1();
    }
    public static void method3(){   //这时编译器会报错
        method2();  
        return this;
    }
}

不能将方法体中的局部变量声明为static

public class Demo {
    public void method1(){
        staitc int x=0;    //编译会报错
    } 
}

如果在执行类时,希望先执行类的初始化动作,可定义一个静态区域

public class Demo {
    static{
	       //dosomething
	}
}

(5)类的主方法

主方法是类的入口点,主方法提供对程序流向的控制

  public static void main(String[] args) {
        //方法体
  }

主方法是静态的,所以如果直接在主方法中调用其它方法,则该方法必须是静态的
主方法没有返回值
主方法的形参为数组。。其中args[0]~args[n]分别代表程序的第一个参数到第n个参数,可以使用args.length获取参数的个数

package com.code;

public class Demo {
    public static void main(String[] args) {
            for (int i=0;i<args.length;i++){
                System.out.println(args[i]);
            }
    }
}

如果没有在Configrations命令中添加参数,则它什么都不会输出

在Run菜单栏中选择Edit Configrations
在Program Argumengts中添加参数
在这里插入图片描述

添加参数后的输出结果:
参数1
参数2
参数3

三·对象

对象是类抽象出来的

(1)对象的创建

java中通过new操作来创建对象/每实例化一个对象就会自动调用一次构造方法

Test test1=new Test();
Test test2=new Test("a");

每个对象都是相互独立的,在内存中占据独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由java虚拟机自带的垃圾回收机制处理,不能再被使用

package com.code;

public class Demo {
    public Demo(){
        System.out.println("创建对象");
    }
    public static void main(String[] args) {
        new Demo();
    }
}

输出结果:
创建对象
(2)访问对象的属性和行为

使用new操作符创建一个对象后,可以使用"对象.类成员"来获取对象的属性和行为。

public class Demo {
   int i=11;
   public Demo(){

   }
   public void call(){
       for(i=0;i<3;i++){
           System.out.print(i+" ");
       }
       System.out.println();
   }
    public static void main(String[] args) {
        Demo d1=new Demo();
        Demo d2=new Demo();
        d2.i=60;
        System.out.println("第一个实例对象调用变量i的结果:"+d1.i++);
        d1.call();
        System.out.println("第二个实例对象调用变量i的结果:"+d2.i);
        d2.call();
    }
}
输出结果:
第一个实例对象调用变量i的结果:11
0 1 2 
第二个实例对象调用变量i的结果:60
0 1 2 

上面例子中,虽然两个对象调用同一个成员变量,结果却不同。因为在打印之前将第二对象里面的成员变量重新赋值。但第一个对象里面的成员变量并没有改变。所以,两个对象产生的相互独立的。
如果希望成员变量不被任何一个对象改变,可以使用static关键字

public class Demo {
   static int i=11;
   public Demo(){

   }
   public void call(){
       for(i=0;i<3;i++){
           System.out.print(i+" ");
       }
       System.out.println();
   }
    public static void main(String[] args) {
        Demo d1=new Demo();
        Demo d2=new Demo();
        d2.i=60;
        System.out.println("第一个实例对象调用变量i的结果:"+d1.i++);
        d1.call();
        System.out.println("第二个实例对象调用变量i的结果:"+d2.i);
        d2.call();
    }
}
输出结果:
第一个实例对象调用变量i的结果:60
0 1 2 
第二个实例对象调用变量i的结果:3
0 1 2 

上述例子中,由于d2.i=60语句改变了静态成员变量的值(改变的是d2),使用对象d1调用成员变量的值也是60.这是因为i被定义为静态成员变量的效果,因为在内存中两个对象同时指向同一块内存区域。d1中的循环又改变了i的值,所以在执行完循环后i变成了3,所以执行d2.i时输出3

(3)对象的引用
类名 对象引用名称

如一个Book类的引用可以使用以下代码

Book book

通常一个引用不一定需要有一个对象相关联。引用与对象相关联的语法如下

Book book=new Book()

Book: 类名
book:对象
new :创建对象操作符

引用只是存放一个对象的内存地址,并非存放一个对象。严格来说,引用和对象是不同的,但可以将这种区别忽略,如可以简单的说book是Book类的一个对象,而事实上应该是book包含Book对象的一个引用

(4)对象的比较

java中有两种比较对象的方式,分别为"=="运算符与equals()方法。这两种方法有着本质的区别

public class Demo {
    public static void main(String[] args) {
         String c1=new String("abc");
         String c2=new String("abc");
         String c3=c1;
         System.out.println("c2==c3的运算结果:"+(c2==c3));
         System.out.println("c2.equals(c3)的运算结果:"+c2.equals(c3));
         System.out.println("c1==c3的运算结果:"+(c1==c3));
         System.out.println("c1.equals(c3)的运算结果:"+c1.equals(c3));
    }
}
输出结果:
c2==c3的运算结果:false
c2.equals(c3)的运算结果:true
c1==c3的运算结果:true
c1.equals(c3)的运算结果:true

"=="和equals()方法比较的内容是不想同的,equals()方法是String类中的方法,它用于比较两个对象引用所指的内容是否相等。“==”运算符比较的是两个对象引用的地址是否相等。由于c1与c2是两个不同的对象引用,两者在内存中的位置不同,而"String c3=c1"是将c1的引用赋值给c3,所以c1和c3这两个对象引用是相等的

(5)对象的销毁

每个对象都有生命周期,当对象的生命周期结束时,分配给改对象的内存地址需要被收回。在其他语言中,需要用户手动回收废弃的对象。java拥有一套完整的垃圾回收机制,不必担心废弃的对象占用内存,垃圾回收器会自动回收无用却占用内存的资源。
以下两种情况会被java虚拟机视为"垃圾”
1.对象引用超过其作用范围,这个对象将视为垃圾

{                                                     //
   Demo demo=new Demo();
}                                                    //作用范围结束

2.将对象赋值为null

{                                                     
   Demo demo=new Demo();
   demo=null;
}    

虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些new操作符创建的对象。某些对象不是通过new操作符在内存中获取储存空间的,这种对象无法被垃圾回收机制所识别。在java中提供了一个finalize()方法,这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法。如果用户在类中定义了finalize()方法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。
垃圾回收或finalize()方法并不保证一定会发生。如果java虚拟机内存损耗待尽,它不会执行垃圾回收处
由于垃圾回收不受人控制,具体执行时间也不确定,所以finalize()方法也就无法执行。为此,java提供了System.gc()方法来强制启动垃圾回收器。

垃圾回收过程
1.发现无用对象
2.回收无用对象占用的内存空间

垃圾回收相关算法
1.引用计数法
2.引用可达法(根搜索算法)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值