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.面向对象上的主要内容,如果未能解决你的问题,请参考以下文章