Java对象与类1.0
Posted 364.99°
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java对象与类1.0相关的知识,希望对你有一定的参考价值。
目录
1.面向对象程序设计概述
面向对象程序设计(object-oriented programming,OOP)
面向对象的程序是由对象组成,每个对象包含对用户公开的特定功能部分和隐藏的实现部分
相对于其他语言的程序员工作过方式:先确定如何操作数据,再决定如何组织数据的结构,OOP却调换了次序,将数据放在了第一位,然后再考虑操作数据的算法。
面向对象更适合解决规模较大的问题
面向过程与面向独享的程序设计对比:
1.1.类
关键名词:
类(class):构造对象的模板(蓝图),创建类的实例(instance)
实例(instance):由类构造(construct)对象的过程称为创建类的实例
实例字段(instance field):对象中的数据,特定的对象都有一组特定的实例字段值,这些值得集合就是这个对象当前的状态(state)
方法(method):操作数据的过程
封装(encapsulation,也称数据隐藏):处理对象的一个重要概念:
从形式上看:将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式
实现封装的关键:绝不能让类中的方法直接访问其他类的实例字段。程序员只能通过对象的方法与对象数据进行交互(“黑盒”特征,提高重用性和可靠性)
继承(inheritance):通过扩展一个类(属性和方法)来建立另一个类的过程(所有的类都源自与Object类,其他的所有类都是扩展自这个Object类)
1.2.对象
对象的三个主要特性:
行为(behavior):可以对对象完成哪些操作(可以对对象应用哪些方法)
状态(state):当调用某些方法时,对象会如何响应
标识(identity):如何区分具有相同行为与状态的不同对象
1.3.识别类
OOP没有“顶部”,不必从顶部的main函数开始编写程序,应首先从识别类开始,然后再为各个类添加方法
识别类的一个简单经验就是在分析问题的过程中寻找名词,而方法对应着动词
如:
在订单处理系统中,有如下名词:
商品(Item)
订单(Order)
送货地址(Shipping address)
付款(Payment)
账户(Account)
从这些名词中就可以得到类Item、Order等
查看动词:
商品被添加到订单中,订单会发货或取消,另外可以对订单完成付款。
其中的添加,发货,取消以及完成付款都要识别出负责完成相应动作的对象。
1.4.类之间的关系
类之间常见的关系
依赖(“uses-a”):A类的方法使用可操纵B类,而B类的变化也可影响到A。这种使用关系是具有偶然性的、临时性的、非常弱,应当尽可能将相互依赖的类减少至最少(减少耦合)
聚合(“has-a”):A类的对象包含了B类的对象
继承(“is-a”):一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)
2.使用预定义类
在Java中,没有类就做不了任何事情。但不是所有的类都表现出面向对象的典型特征,如Math类,可以直接使用Math类的方法,而不需要了解它具体是如何实现。这是由于封装,Math类只封装了功能,不需要隐藏数据,由于没有数据,所以不必考虑创建对象和初始化它们的实例字段,因为没有实例字段。
2.1.对象与对象变量
使用对象,必须先构造对象,并指定其初始状态,接着使用对象方法。
Java中,使用构造器(constructor)构造新实例。
构造器名字与类名相同,使用关键字new
进行构造新对象
对象可以调用类方法,对象变量则不行
以下使用Date类:
注意:Java中,对象变量并没有包含一个对象,只是引用了一个对象,任何变量的值都是存储在另外一个地方的某个对象的引用。new操作符的返回值也是一个引用。
2.2.LocalDate类
Date类的实例有一个状态:特定的时间点
Java时间是使用距离一个固定时间点的毫秒数表示的,此时间点称为纪元(epoch),具体为UTC(Universal Time Coordinated ,国际协调时间)时间1970年1月1日 00:00:00
Java类库拥有两个类:
Date类:表示时间点
LocalDate类:日历表示法表示日期
不能使用构造器来构造LocalDate类的对象,应该使用静态工厂方法(factory method),它会代调用构造器
import java.time.LocalDate;
public class TestDate {
public static void main(String[] args) {
LocalDate.now();//构造一个新对象
LocalDate.of(1999,10,2);//构造一个特定的日期对象
LocalDate newYearsEve = LocalDate.of(1999,12,31);//将构造的对象保存在一个对象变量中
//使用LocalDate的方法
int year = newYearsEve.getYear();
int month = newYearsEve.getMonthValue();
int day = newYearsEve.getDayOfMonth();
System.out.printf("%d年%d月%d日%n",year,month,day);
LocalDate aThousandDaysLater = newYearsEve.plusDays(1000);//得到一个新的LocalDate
int year1 = aThousandDaysLater.getYear();
int month1 = aThousandDaysLater.getMonthValue();
int day1 = aThousandDaysLater.getDayOfMonth();
System.out.printf("%d年%d月%d日%n",year1,month1,day1);
}
}
关键字 | 简介 |
---|---|
static LocaDate now() | 构造一个表示当前日期的对象 |
static LocalDate of(int year,int month,int day) | 构造一个表示给定日期的对象 |
int getYear int getMonthValue() int getDayOfMonth() | 得当当前日期的年、月、日 |
DayOfWeek getDayOfWeek() | 得到当前日期是星期几,作为DayOfWeek类的一个实例返回,调用getValue()取值1~7 |
LocalDate plusDays(int n) LocalDate minusDays(int n) | 生成当前日期之后或之前n天的日期 |
2.3.更改器方法与访问器方法
更改器方法会将原对象的属性值改变,而访问器方法(如plusDays)会创建一个新的对象来存储得到的数值,而不改变原对象的属性值
3.用户自定义类
最简单的类定义形式:
class ClassName{
field1;
filed2;
…
constructor1;
constructor2;
…
method1;
method2;
…
}
自定义一个简单的HolidayLife类
import java.time.LocalDate;
class HolidayLife {
//instance fields
private int days;//private:访问修饰符,仅本类可以访问
private LocalDate date;
private int studyTime;
private int workoutTime;
//constructor(默认自带一个无参构造器)
//带一个参数的构造器(本案例中并没使用,只是写写)
public HolidayLife(int days){
this.days = days;//this表示此对象
}
//带四个参数的构造器
public HolidayLife(int days,LocalDate date,int studyTime,int workoutTime){
this.days = days;
this.date = date;
this.studyTime = studyTime;
this.workoutTime = workoutTime;
}
//method
public int getDays(){
return days;
}
public LocalDate getDate(){
return date;
}
public int getStudyTime(){
return studyTime;
}
public int getWorkoutTime(){
return workoutTime;
}
}
OnHoliday
import java.time.LocalDate;
public class OnHoliday {
public static void main(String[] args) {
//声明一个对象数组
HolidayLife []holiday = new HolidayLife[5];
//设置假期起始日
LocalDate date = LocalDate.of(2021,5,1);
//设置对象数组的内容(利用带参的构造方法实例化5个对象)
for (int i = 0;i < holiday.length;i++){
holiday[i] = new HolidayLife(1,date.plusDays(i),(int)(2+Math.random()*5),(int)(1+Math.random()*5));
}
//输出假期内容
String str = "%tF,第%d天假期,学习时长%d时,锻炼时长%d时%n";
for (HolidayLife each : holiday){
System.out.printf(str,each.getDate(),each.getDays(),each.getStudyTime(),each.getWorkoutTime());
}
}
}
输出结果
3.1.构造器
构造器与类同名,在构造类的对象时,构造器会运行,从未将实例字段初始化为所希望的初始状态(初始化构造器中的参数)
构造器结合new运算符来调用
每个类有一个或以上的构造器
构造器的参数数量不定
构造器没有返回值
不能对一个已经存在的对象使用构造器来重新设置实例字段
3.2.使用null引用
一个对象性变量可包含一个对象的引用,或一个特殊值null,null表示没有引用任何对象
注意: 如果对null值应用一个方法,会抛出NullPointerException异常
这是一个很严重的错误,类似于“索引越界”异常,当程序没有“捕获”异常,程序就会终止。
定义一个类,需要知道哪些字段可能为null
当调用构造器时为days
提供的实参为null时,有以下解决方法
1.“宽容型”方法:将null参数转换为一个适当的非null值
if (days == null) days = null;else days = n;
2.“严格型”方法(Java9):直接拒绝null参数
public HolidayLife(int days,LocalDate date,int studyTime,int workoutTime){
Objects.requireNonNull(days,"The days can't be null");//拒绝days为null
this.days = days;
this.date = date;
this.studyTime = studyTime;
this.workoutTime = workoutTime;
}
3.3.隐式参数与显示参数
隐式参数(implicit):出现在方法名前的类的对象,没有出现在方法声明中
显示参数(explicit):位与方法名后括号中的数值,显示地出现在方法声明中
this
:在方法中指示隐式参数
3.4.封装
封装: 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问
优点: 可以改变内部实现,而除了该类的方法外,不会影响其他代码
更改器方法可以完成错误检查
实现: 一个私有化的数据字段,修改属性的访问权限为private
一个公共的访问器方法,创建getter方法
一个公共的字段更改器方法,创建setter方法
注意: 不要编写返回可变对象引用的访问其方法,会破坏封装性
需要返回一个可变对象的引用,需要对它进行克隆(clone
方法)
3.5.访问权限
类型 | 本类 | 同包子类 | 不同包子类 | 同包类 | 其他类 |
---|---|---|---|---|---|
public | 可访问 | 可继承 | 可继承 | 可访问 | 可访问 |
protected | 可访问 | 可继承 | 可继承 | 可访问 | 不可访问 |
package | 可访问 | 可继承 | 不可继承 | 可访问 | 不可访问 |
private | 可访问 | 不可继承 | 不可继承 | 不可访问 | 不可访问 |
3.6.私有方法
在实现一个类时,由于公共数据非常危险,所以应当将所有的数据字段都设置为私有的。
虽然大多数方法都被设置为公共的,但在某些特殊情况下,将方法设置为私有的很有用
实现: 使用private将方法声明为私有
优点: 只要方法是私有的,类的设计者就可以确信它不会再别处使用,所以可以将其删去。如果是一个公有方法,就不能简单地将其删除,因为有可能有其他代码依赖这个方法。
3.7.final实例字段
将实例字段定义为final,这样的字段必须在构造对象时初始化(即确保在每一个构造器执行之后,这个值已经设置),并且之后不能再修改这个字段
对于类型为基本类型或者不可变类的字段尤其有用
以上是关于Java对象与类1.0的主要内容,如果未能解决你的问题,请参考以下文章