Java全栈JavaSE:12.面向对象上

Posted new nm个对象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java全栈JavaSE:12.面向对象上相关的知识,希望对你有一定的参考价值。

1.什么是面向对象

(1)面向对象与面向过程

  • 面向对象:简单的可以理解为将复杂的事情分解为许多简单的事情。再将这些简单的事情的解决办法封装到类对象中。就像我们造汽车一样,并不会一步一步的去造,而是将汽车分解为许多零部件,如何将这些零部件组装起来就行了。
  • 面向对象是一种框架,一种思想。当我们具体实现每一个小功能时,仍然是使用面向过程的思想。

(2)什么是面向对象

  • 面向对象的核心就是类和对象。
  • 类:就是一类事务的抽象,它有该类事务的属性和方法。例如:人我们可以抽象为一个类,它们都能移动,都能叫,都需要吃饭等等。
  • 对象:对象是类的具体表现,类是对象的模板。对象都是通过类来产生的。例如:人是一个类,张三就是一个具体的对象。

2.类和对象


环顾周围,你会发现很多对象,比如桌子,椅子,同学,老师等。桌椅属于办公用品,师生都是人类。那么什么是类呢?什么是对象呢?

什么是类

  • :是一类具有相同特性的事物的抽象描述,是一组相关属性行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。

  • 类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象。我们要造一个汽车,怎么样造?类就是这个图纸,规定了汽车的详细信息,然后根据图纸将汽车造出来。

    类:我们叫做class。 对象:我们叫做Object,instance(实例)。以后我们说某个类的对象,某个类的实例。是一样的意思。

    示例1:

    英雄联盟、王者荣耀中的类和对象

英雄就是类,具体的英雄,盖伦、提莫是对象。

示例2:

月饼模具和月饼

月饼模具是类,使用月饼模具制作的一个个月饼就是对象

现实中,描述一类事物:

  • 属性:就是该事物的状态信息。
  • 行为:就是该事物能够做什么。

举例:小猫。

​ 属性:名字、体重、年龄、颜色。
​ 行为:走、跑、叫。

什么是对象

  • 对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为。

现实中,一类事物的一个实例:一只小猫 。

举例:一只小猫。

​ 属性:tom、5kg、2 years、yellow。
​ 行为:溜墙根走、蹦跶的跑、喵喵叫。

类与对象的关系

  • 类是对一类事物的描述,是抽象的
  • 对象是一类事物的实例,是具体的
  • 类是对象的模板,对象是类的实体

3.类的定义和对象的创建

事物与类的对比

现实世界的一类事物:

属性:事物的状态信息。
行为:事物能够做什么。

Java中用class描述事物也是如此:

成员变量:对应事物的属性
成员方法:对应事物的行为

类的定义格式

public class ClassName {
  //成员变量
  //成员方法 
}
  • 定义类:就是定义类的成员,包括成员变量成员方法
  • 成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外
  • 成员方法:和以前写的main方法格式类似。只不过功能和形式更丰富了。在类中,方法外。

类的定义格式举例:

public class Person {
  	//成员变量
  	String name;//姓名
    int age;//年龄
    boolean isMarried;
    
    public void walk(){
        System.out.println("人走路...");
    }
    public String display(){
        return "名字是:" + name + ",年龄是:" + age + ",Married:" + isMarried;
    }
}

对象的创建

创建对象:

new 类名()//也称为匿名对象

//给创建的对象命名
//或者说,把创建的对象用一个引用数据类型的变量保存起来
类名 对象名 = new 类名();

类似于:

System.out.println("高老师年龄是:" + 18);//如果确定只在这里一次性使用,那么可以不用变量保存(#^.^#)

//把18用int类型的age变量保存起来,方便后面使用
int age = 18;
System.out.println("高老师年龄是:" + age);
System.out.println("仓老师比高老师大10岁,年龄是:" + (age+10));

那么,对象名中存储的是什么呢?答:对象地址

class Student{
    
}
public class TestStudent{
    //Java程序的入口
    public static void main(String[] args){
        System.out.println(new Student());//Student@7852e922

        Student stu = new Student();
        System.out.println(stu);//Student@4e25154f
        
        int[] arr = new int[5];
		System.out.println(arr);//[I@70dea4e
    }
}
//Student和TestStudent没有位置要求,谁在上面谁在下面都可以
//但是如果TestStudent类的main中使用了Student类,那么要求编译时,这个Student已经写好了,不写是不行的
//如果两个类都在一个.java源文件中,只能有一个类是public的

发现学生对象和数组对象类似,直接打印对象名和数组名都是显示“类型@对象的hashCode值",所以说类、数组都是引用数据类型,引用数据类型的变量中存储的是对象的地址,或者说指向堆中对象的首地址。

那么像“Student@4e25154f”是对象的地址吗?不是,因为Java是对程序员隐藏内存地址的,不暴露内存地址信息,所以打印对象时不直接显示内存地址,而是JVM提取了对象描述信息给你现在,默认提取的是对象的运行时类型@代表对象唯一编码的hashCode值。

创建对象内存图


注意:每创建一个对象,就会分配一块独立的空间。用于储存相关成员变量的信息。

4. 包(Package)

1、包的作用

(1)可以避免类重名:有了包之后,类的全名称就变为:包.类名

(2)分类组织管理众多的类

例如:

  • java.lang----包含一些Java语言的核心类,如String、Math、Integer、 System和Thread等,提供常用功能
  • java.net----包含执行与网络相关的操作的类和接口。
  • java.io ----包含能提供多种输入/输出功能的类。
  • java.util----包含一些实用工具类,如集合框架类、日期时间、数组工具类Arrays,文本扫描仪Scanner,随机值产生工具Random。
  • java.text----包含了一些java格式化相关的类
  • java.sql和javax.sql----包含了java进行JDBC数据库编程的相关类/接口
  • java.awt和java.swing----包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。

(3)可以控制某些类型或成员的可见范围

如果某个类型或者成员的权限修饰缺省的话,那么就仅限于本包使用

2、声明包的语法格式

package 包名;

注意:

(1)必须在源文件的代码首行

(2)一个源文件只能有一个声明包的语句

包的命名规范和习惯:
(1)所有单词都小写,每一个单词之间使用.分割
(2)习惯用公司的域名倒置

例如:com.atguigu.xxx;

建议大家取包名时不要使用“java.xx"包

3、如何跨包使用类

前提:被使用的类或成员的权限修饰符是>缺省的,即可见的

(1)使用类型的全名称

例如:java.util.Scanner input = new java.util.Scanner(System.in);

(2)使用import 语句之后,代码中使用简名称

import语句告诉编译器到哪里去寻找类。

import语句的语法格式:

import.类名;
import.*;
import static.类名.静态成员; //后面再讲

注意:

使用java.lang包下的类,不需要import语句,就直接可以使用简名称

import语句必须在package下面,class的上面

当使用两个不同包的同名类时,例如:java.util.Date和java.sql.Date。一个使用全名称,一个使用简名称

示例代码:

package com.atguigu.bean;

public class Student {
	// 成员变量
	private String name;
	private int age;

	// 构造方法
	public Student() {
	}

	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// 成员方法
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getAge() {
		return age;
	}
}
package com.atguigu.test;

import java.util.Scanner;
import java.util.Date;
import com.atguigu.bean.Student;

public class Test{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        Student stu = new Student();
        String str = "hello";
        
        Date now = new Date();
        java.sql.Date d = new java.sql.Date(346724566);        
    }
}

5. 成员变量

1、成员变量的分类

实例变量:没有static修饰,也叫对象属性,属于某个对象的,通过对象来使用。也叫非静态成员变量

类变量:有static修饰,也叫类变量,属于整个类的,不是属于某个实例。也叫静态成员变量

2、如何声明成员变量?

【修饰符】 class 类名{
    【修饰符】 数据类型  属性名;    //属性有默认值
    【修饰符】 数据类型  属性名 =; //属性有初始值
}

说明:属性的类型可以是Java的任意类型,包括基本数据类型、引用数据类型(类、接口、数组等)

例如:声明一个中国人的类

class Chinese{
	static String country;
	String name;
    char gender = '男';//显式赋值
}

3、如何在类外面访问成员变量?

(1)类变量

类名.静态成员变量  //推荐

对象名.静态成员变量 //不推荐

(2)实例变量

对象名.非静态成员变量  //只能使用这种方式

例如:

public class TestChinese {
	public static void main(String[] args) {
		//类名.静态成员变量
		System.out.println(Chinese.country);
		//错误,非静态成员变量必须通过对象.进行访问
//		System.out.println(Chinese.name);
		
		Chinese c1 = new Chinese();
		//对象名.非静态成员变量
		System.out.println(c1.name);
		//静态的成员变量也可以通过对象.进行访问
		//对象名.非静态成员变量
		System.out.println(c1.country);
        System.out.println(c1.gender);
	}
}
class Chinese{
	static String country;
	String name;
    char gender = '男';
}

4、成员变量的特点

(1)成员变量有默认值

基本类型整数(byte,short,int,long)0
浮点数(float,double)0.0
字符(char)‘\\u0000’
布尔(boolean)false
数据类型默认值
引用类型数组,类,接口null

(2)类变量的值是所有对象共享的,而实例变量的值是每个对象独立的

public class TestChinese {
	public static void main(String[] args) {
		Chinese c1 = new Chinese();
		Chinese c2 = new Chinese();
		
		c1.name = "张三";
		c2.name = "李四";
        c2.gender = '女';
		
//		c1.country = "中国";
		Chinese.country = "中国";//推荐
		
		System.out.println("c1.country = " + c1.country + ",c1.name = " + c1.name + ",c1.gender = " + c1.gender);
		System.out.println("c2.country = " + c2.country + ",c2.name = " + c2.name + ",c2.gender = " + c2.gender);
	}	
}
class Chinese{
	static String country;
	String name;
    char gender = '男';
}

5、成员变量的内存图

​ 内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。Java虚拟机要运行程序,必须要对内存进行空间的分配和管理,每一片区域都有特定的处理数据方式和内存管理方式。

区域名称作用
程序计数器程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址
本地方法栈当程序中调用了native的本地方法时,本地方法执行期间的内存区域。存放的是c/c++等方法
方法区存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
堆内存存储对象(包括数组对象),new来创建的,都存储在堆内存。
虚拟机栈用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。
class Test08FieldSave{
	public static void main(String[] args){
		Chinese c1 = new Chinese();
		c1.name = "张三";
		System.out.println(c1.country);//静态变量,也可以使用"对象名."进行访问
		System.out.println(c1.name);//非静态的实例变量通过"对象名."进行访问
		
		
		Chinese c2 = new Chinese();
		c2.name = "李四";
		System.out.println(c2.country);
		System.out.println(c2.name);
		
		System.out.println("--------------------------------------");
		//其中一个对象将静态变量的值修改了,其他对象都会改变
		//因为静态变量只存一份
		c1.country = "中华人民共和国";
		System.out.println(c1.country);
		System.out.println(c2.country);
		System.out.println(Chinese.country);
		
		
		//其中一个对象将非静态实例变量修改了,其他对象不受影响
		c1.name = "张三丰";
		System.out.println(c1.name);
		System.out.println(c2.name);
	}
	
}

class Chinese{
	static String country = "中国";//静态变量,所有中国人的国家的名称是一样,只需要存储一份
	String name;//实例变量,每一个中国人的姓名是独立,每一个对象单独存储
}

运行结果如下:

中国
张三
中国
李四
--------------------------------------
中华人民共和国
中华人民共和国
中华人民共和国
张三丰
李四

class MyDate{
	int year;
	int month;
	int day;
}
class Employee{
	String name;
	MyDate birthday;
}
class Test09FieldExer3{
	public static void main(String[] args){
		//创建两个员工对象
		Employee e1 = new Employee();
		Employee e2 = new Employee();
		
		//为两个员工对象的成员变量赋值
		e1.name = "张三";
		e1.birthday = new MyDate();
		
		e2.name = "李四";
		e2.birthday = new MyDate();
		
		e1.birthday.year = 2000;
		e1.birthday.month = 1;
		e1.birthday.day = 1;
		
		e2.birthday.year = 2000;
		e2.birthday.month = 3;
		e2.birthday.day = 8;
		
		System.out.println("第一个员工,姓名:" + e1.name +",生日:" + e1.birthday.year + "年" + e1.birthday.month + "月" + e1.birthday.day + "日");
		System.out.println("第二个员工,姓名:" + e2.name +",生日:" + e2.birthday.year + "年" + e2.birthday.month + "月" + e2.birthday.day + "日");
	}
}

运行结果如下:

第一个员工,姓名:张三,生日:2000年1月1日
第二个员工,姓名:李四,生日:2000年3月8日

实例变量(非静态变量内存图)

类变量(静态变量内存图)

  • 问题:在上面的内存图分析中,我们发现每一次创建对象都会给变量country开辟空间,但每一次赋值都是一样的。我们是否可以将country的空间实现复用呢
  • 解决:将country设置为类变量

6、类变量与实例变量的区别

  • 声明方式不同:类变量需要加static修饰,实例变量不需要
  • 调用方式不同:类变量使用类名去调用,实例变量只能使用实例对象去调用
  • 内存不同:类变量存放在方法区中,所有对象共享一份。实例变量存放在堆中,每一个对象一份
  • 初始化时间不同:类变量随着类的加载完成初始化;实例变量随着实例对象的创建完成初始化。即类变量早于实例变量完成初始化
  • 销毁时间不同:类变量随着类的销毁而销毁;实例变量当没有引用指向时,会被垃圾回收器(GC)回收销毁。即类变量的生命周期比实例变量更长

7.成员变量练习

练习1
需求:

  • 声明一个银行账户类,有属性:利率、账号、余额
  • 在测试类的main中,创建账户类的两个对象,其中所有账户的利率是相同的,都是0.035,而账号和余额是不同的,并打印显示

银行账户类代码:

package com.oy.面向对象.opp1;

public class Account {
    // 账号属性
    String account;
    // 利率属性
    static double rate = 0.035;
    // 余额属性
    double balance;
}

测试类代码如下:

package com.oy.面向对象.opp1;

public class Test {
    public static void main(String[] args) {
        //声明第一个账户
        Account ac1 = new Account();
        ac1.account = "adasfvdsgffhn";
        ac1.balance = 259632.258;
        System.out.println("账户为:"+ ac1.account+"; 利率为:"+Account.rate+"; 余额为:"+ac1.balance);
        //声明第二个账户
        Account ac2 = new Account();
        ac2.account = "asfdscbvbghgggg";
        ac2.balance = 3005.25;
        System.out.println("账户为:"+ ac2.account+"; 利率为:"+Account.rate+"; 余额为:"+ac2.balance);
    }
}

运行测试类结果如下:

账户为:adasfvdsgffhn; 利率为:0.035; 余额为:259632.258
账户为:asfdscbvbghgggg; 利率为:0.035; 余额为:3005.25

练习2
需求:

  • 声明一个MyDate类型,有属性:年,月,日

  • 声明另一个Employee类型,有属性:姓名(String类型),生日(MyDate类型)

  • 在测试类中的main中,创建两个员工对象,并为他们的姓名和生日赋值,并显示

代码如下:

package com.oy.面向对象;

public class Demo3 {
    public static void main(String[] args) {
        // 声明第一个员工对象
        Employee employee1 = new Employee();
        employee1.name = "张三";
        //注意:员工的生日属性应该是一个MyDate对象
        employee1.birthday &

以上是关于Java全栈JavaSE:12.面向对象上的主要内容,如果未能解决你的问题,请参考以下文章

Java全栈JavaSE:13.面向对象中

我的全栈之路-Java架构师技术栈

Java全栈JavaSE:21.集合之Map

Java全栈JavaSE:20.集合之CollectionIterator迭代器ListSet

Java面向对象-方法的重载

Java全栈JavaSE:19.常用类之大数运算日期和日历包装类