Java初了解(五)--- 面向对象基础
面向过程和面向对象的区别?
- 面向过程,关注点,解决问题步骤,执行过程
- 面向对象,关注点,完成任务中实体(对象),对象属性,对象方法
- 面向对象建立模型,这个模型非常难创建。设计内容太过广泛,有时没必要。
- 在代码修改时,面向对象想的多,但想的周全,可能就不需要改代码了,而面向过程,必须修改代码。
- 面向对象是主流思考方式。但实际开发是两者结合。
一、面向对象基础
面向对象设计的基本过程:
- 首先分析实际需要解决的问题,从中提取出需要设计的对象,然后编写这些对象所对应的类,最后通过集成这些对象的功能解决需要求解的问题
基本概念:
- 对象:面向对象的核心,就是现实世界中实体在计算机逻辑中的映射和体现
- 类:描述同类对象的公共属性和行为
- 属性:描述对象的状态,主要指对象内部所包含的各种静态信息
- 行为:又称为对象的操作,主要描述内部的各种动态信息
操作的作用是设置和改变对象的状态
特点:
面向对象设计方法主要概括为继承、封装和多态三大特点
- 封装:就是将事物的内部细节隐藏起来,对外提供一致的公共接口间接访问隐藏数据。
Java语言中通过类机制体现其封装性,类将相关的数据和方法封装起来。
优点:耦合和交叉大大减少,降低开发过程的复杂性,减少错误的可能,使其具有良好的可维护性。
- 继承:是存在于面向对象 程序的类之间的一种关系。
一个父类可以被多个子类继承,子类可以定义属于自己的特有属性和方法。
优点:结构清晰,易于理解,可以降低维护的工作量,提高效率。
多态:指多种表现形式,就是对象响应外部激励而使其形成发生改变的现象。
一般有两种情况:- 通过类之间继承导致的同名方法重写体现
- 通过同一个类中同名方法的重载体现
优点:提高了程序的抽象程度和简洁性,最大限度的降低了类之间的耦合性,方便程序的修改和拓展。对程序的设计、开发和维护都有很大的好处
二、类
类是Java程序的基本单元,Java程序的编写过程就是定义类的过程。
(一)类的定义
分为两部分:类的声明(类头)、类体
class 类名{
类体的内容
}
1、类声明
class关键字标志着一个类定义的开始(区分大小写),class后面是类名,由自己命名(遵循Java命名规范即可),且能体现类的主要功能或作用。例如:
class Student{ //定义类 Student
}
class Teacher{ //定义类 Teacher
}
2、类体
类声明之后的一对大括号以及他们之间的内容称作类体。
类体的构成:
- 成员变量的定义,用来描述属性
- 方法的定义,用来描述功能
类的定义案例:
class Student {
//成员变量的定义
String stuName;
int stuAge;
//方法的定义,get/set
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
}
(二)成员变量和局部变量
- 在类体内部、方法体外定义的变量称为成员变量
- 在方法体中定义的变量和方法参数称为局部变量
定义格式:
变量类型 变量名;
1、变量的类型
可以是Java允许的任何合法的数据类型,即8种基本数据类型和引用类型。例如:
Integer stuAge; //引用类型
int age = 9; //基本数据类型
注意:成员变量如果没有被初始化,系统会自动为其分配初始值,通常引用类型的成员变量初始值为null,基本数据类型的成员变量初始值则各不相同
2、变量的有效范围
成员变量在整个类中都有效,局部变量只有在定义它的方法中有效。方法参数在整个方法内有效,方法内定义的局部变量从它定义的位置之后开始有效。
class Student {
int number = 10; //成员变量,在整个类中有效
int getSum() {
int sum = 0; //局部变量,只有在getSum中有效
for (int i = 0; i < number; i++) {
sum = sum + i;
}
return sum;
}
}
3、成员变量的隐藏
当全局变量与局部变量的名字相同时,则全局变量的名字被隐藏,即全局变量在这个方法中暂时失效。如果还想在这个方法中使用全局变量,需要使用this关键字。例如:
class Student {
int number = 10; //全局变量
int getSum() {
int sum = 0; //局部变量
System.out.println(number); //输出0
System.out.println(this.number); //输出10
}
}
注意:全局变量的有效性与它在类中的书写位置的先后无关,但通常习惯于先定义属性再定义功能。
(三)方法
方法是可执行的代码,用于描述对象的行为。换句话说“方法就是完成某种功能的程序块”
在Java中方法必须定义在类体中,也被称做成员方法。
- 方法的构成:方法头和方法体
一般格式:
方法声明{
方法体;
}
1、方法声明
具体格式:
返回值类型 方法名(参数列表)
返回值类型。可以是基本数据类型,引用类型和空类型(void)。当一个方法不需要返回数据时,返回类型必须为void,否则方法体中必须包含return语句。
- 方法名。是方法之间区别的标识。Java中允许多个方法同名。
- 参数列表。是一串用 “,” 隔开的变量声明
一般格式:(<数据类型1 变量名1>,…,<数据类型n 变量名n>)
例如:
void showMessage() //无参方法声明
void setAge(int age) //包含一个参数的方法的声明
int max(int id,int age) //包含多个参数的方法的声明
2、方法体
- 主要由局部变量和语句构成。
- 方法体也可以是空
例如:
void setName(String name){
}
类中定义的方法的作用:
- 围绕类的属性进行各种操作
与其他类或对象进行数据交流、消息传递等。
class Student {
int stuId;//学号
String stuName;//姓名
String deptName;//院系名称
int getStudentId() { //获取当前对象的学号
return stuId;//返回当前对象的学号
}
boolean setStudentId(int studentId) { //设置学号
if (studentId > 0) {
stuId = studentId;//修改属性studentId
return true;//修改成功true
}else {
return false;//修改失败返回false
}
}
}
(四)构造方法
又被成为“构造器”、“构造函数”
特殊性主要体现在:
- 构造方法的方法名与类名相同
- 构造方法无返回值
- 构造方法的主要作用是完成类实例的初始化操作
- 构造方法只能通过new运算符调用,不能通过其他方法
- 一个类可以定义多个构造方法,根据传递给构造方法的参数的数目和类型,系统自动帮助选择哪一个构造方法。
案例代码:
class Student {
int stuId;//学号
String stuName;//姓名
int deptNameId;//院系名称
//参数为空的构造方法
public Student() {
//设置姓名、学号、编号
stuName = "丹尼尔";
stuId = 00700;
deptNameId = 15;
}
//带参数的构造方法
public Student(String name,int sId,int dId) {
//根据参数设置姓名、学号、编号
stuName = name;
stuId = sId;
deptNameId = dId;
}
}
说明:构造方法的调用在用new关键字创建类对象时由系统自动完成,其参数的传递和形实结合过程也由系统在自动调用的同时自动完成。
创建一个新的学生对象:
Student student = new Student();
//User叫做类,user叫做对象,实例,这个过程也叫实例化
构造方法的作用:
- 为每个新建的对象赋初始值,通过构造方法,可以根据需要为对象每个属性定义初始值,从而保证每一个新建的对象处于正常的状态。
也可以不定义构造方法,编译器会自动创建一个默认的构造方法。名字与类名相同,没有任何的形式参数,也不完成任何的操作,所有成员变量根据其所属类型被赋值为默认值。例如:
Student(){ }//参数为空的构造方法
可以自己new一个新的对象,例如:
Student student = new Student();
注意:一旦类中存在自己创建的构造方法,并且这个构造方法是有参数的,那么再尝试调用一个无参的构造方法将会出错。(此时已经没有隐含的缺省的构造方法了)
三、对象
对象是类的实例,对象创建之后,可以相互之间进行通信,从而完成一定的功能。对象在使用完毕之后,系统会自动释放它,占用的资源会被收回。因此对象要经历 “创建并初始化———使用———释放” 这样一个生命周期。
(一)对象的创建
java中万物皆对象
使用new创建对象,一个类可以创建n个对象
User u1 = new User();
User u2 = new User();
关键字new是调用相应类中的构造方法;来为对象分配相应的空间,并且为对象进行初始化,对象建立与初始化是同时的,即在分配内存空间的同时根据构造方法的定义将对象的初始状态存放在内存中。
(二)对象的使用
使用方式:
- 通过使用对象的成员变量来使用对象
通过调用对象的方法来使用对象
objectReference.variable;//使用对象的变量
objectReference.methodName(paramlist);//使用对象的方法
对象变量的调用就是用语句访问对象的变量,通过这种调用可以使用并修改变量;
对象方法的调用时获得对象功能的一种手段,可以避免对变量的直接操作,更加安全。
(三)对象引用与对象实体
对象引用与对象实体是相互独立的。
案例分析:
Student li = new Student("小李",1001,12);
Student zheng = new Student("小郑",10002,16);
两个对象分配不同的内存空间。假设,使用了赋值语句如下:
zheng = li;
这样li和zheng在本质上是一样的,但是系统来看他们都是0x1032,系统将取消原来原来分配给zheng 的内存,li和zheng 有相同的实体,内存空间模型图如下:
一个类创建的两个对象,如果具有相同的引用,那么就具有完全相同的实体。没有实体的对象称作空对象,空对象不能使用,即不能调用空对象的属性和方法。
(四)垃圾回收机制
Java系统具有所谓的垃圾回收机制,垃圾回收器(GC)在后台运行,定时查看所有的对象,识别那些不再被引用的对象(垃圾),并给予释放,回收分配给这些对象的内存。因此Java中很少出现“内存泄露”的情况。
四、static关键字
如果一个成员被声明为static,那么他就能够在其所在类的任何对象创建之前被访问,而不必通过对象引用该成员,用static声明的变量、方法和代码块分别被称为类变量、类方法和静态代码块。
(一)类变量
又叫“静态变量”。不依赖于对象,在“类装载”时已经分配了内存。可直接通过类来访问,也就是说:类变量不依附于任何对象。
class Student {
int stuId;
static String stuName = "丹尼尔";//类变量的定义
Student(int stuId) {
this.stuId = stuId;
}
}
class EX{
public static void main(String[] args) {
Student s1 = new Student(1000);
System.out.println(s1.stuName);//通过变量名访问类变量
Student.stuName = "邦德";//通过类名访问类变量
System.out.println(s1.stuName);
}
}
类变量可以被类的任何实例访问,但应该避免使用对象访问类变量,因为这样可能在读代码时造成误解,以为类变量是实例变量,通常建议通过类来访问类变量。
(二)类方法
分类:类方法和实例方法
- 类方法只与类有关,他不是对类的实例操作,而是对类的本身操作。
因此他不具有访问本类的各个对象的实例变量和实例方法的能力,但类可以访问类变量,特别是在类变量被声明为private的时候,通常在其它类中使用类方法以操作该private的类变量。 实例方法是与具体对象有关,它依赖于具体的对象
class Student {
static int stuId;
Student(int stuId) {
this.stuId = stuId;
}
static int getStuId() { //类方法的定义
return stuId;
}
}
class EX{public static void main(String[] args) {
Student s1 = new Student(1000);
System.out.println(Student.getStuId()); //通过类名访问类变量
}
}
一般情况下直接通过类名访问类方法。
在以下两种情况下使用类方法:
- 如果方法的所有参数可以直接给定,不需要访问实例变量时可使用类方法。例如java.lang.Math类。
- 如果方法仅仅访问类变量时,可将其定义为类方法。
(三)静态代码块
是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,他不在任何的方法体内,JVM加载类时会执行这些静态代码块,如果static代码块有多个,将会按照在类中出现的先后顺序依次执行它们,每个代码块只会被执行一次。
class Student{
static {
System.out.println("这是一个学生类");
stuName = "丹尼尔";
}
String stuName;
string getName(){
return stuName;
}
}
五、this关键字
this关键字,表示某个对象,这个变量的类型是当前类的类型,因此可以在实例方法和构造方法中使用。
(一)在构造方法中使用this
this出现在类的构造方法中,代表使用该构造方法时所创建的对象。
class Student {
int stuId;
String stuName;
void init() {
stuName = "daniel";
stuId = 10011;
}
public Student() {
this.init(); //在构造方法中使用this
}
}
class EX{
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("学号:"+ s1.stuId + "姓名:" + s1.stuName);
}
}
运行结果:
学号:10011 姓名:daniel
(二)在实例方法中使用this
在实例方法中,代表正在使用该方法的当前对象。实例方法可以操作类的成员变量。
默认格式:
this.成员变量
类的实例方法可以调用类的其他方法,默认格式:
this.方法名(参数列表)
class Test{
int x;
void function1(){
this.x = 100; //可以省略this
}
void function2(){
this.function1(); //可以省略this
}
}
this不能出现在类方法中,因为类方法可以通过类名直接调用,此时可能还没有产生任何现象。
六、包
(一)概念
包是一种类似于文件夹的组织形式,包把各种类组织起来,一方面对类的命名空间进行管理,另一方面作为隐含的访问控制修饰符,是信息隐藏和封装的有力工具。
Java的类库是系统提供的已实现的标准类的集合,是Java编程的API(Application Programming Interface),可以帮助开发者方便、快捷的开发Java程序。Java类库被划分成不同的包,每个包中都有若干个具有特定功能和相互关系的类和接口。
只需要使用import语句将相关的类库(包)加载到程序中就可以了,下面列出几种常用的重要的类库(包):
- java.lang
核心类库,包含java程序的基础类,涉及领域有基本数据类型、基本数学类、字符串、线程等。这个类库的加载是由Java编译器自动完成的,不需要import语句来专门引入。 - java.util
包括向量类(Vector)、日期类(Calendar)、时间类(Date)、堆栈类(Stack)等,需要import语句来专门引入 - java.io
提供了对计算机中存储的文件进行相关操作的类,文件类(File)、文件输入流类(FileInputStream)、文件输出流类(FileOutputStream)等。需要import语句来专门引入。 - java.net
用来实现网络功能的类库,由支持底层Internet编程和实现www/HTML应用的类组成。利用此类,可以方便的编写具有网络功能的程序。需要import语句来专门引入。 - java.sql
主要用于将 SQL 语句传递给数据库,但它还可以用于以表格方式从任何数据源中读写数据。通过接口的 javax.sql.RowSet 组可以使用的 reader/writer 实用程序,可以被定制以使用和更新来自电子表格、纯文本文件或其他任何表格式数据源的数据。
(二)创建包
创建包需要使用package关键字,一般格式:
package 包名;
注意:这条语句必须放在源文件的第一行,并且在一个源文件中只能有一条package语句。
合法的创建包的语句:
package newpackage;
package society.family;
第二个创建包的语句中 “ . “ 代表了目录分割符,即这条语句创建了两个文件夹
package xlyDay01;//这就是一个包
public class Demo01 {
public static void main(String[] args) {
System.out.println("hello world!!!");
}
}
(三)导入包
1、使用类全名
类全名可以唯一确定一个类,在引用一个其他包中的类时,可以在类名前面加上包名作为前缀。
package schools;
public class Student {
public int stuCode;
public int deptCode;
public String stuName;
public Student(String name,int sCode,int dCode) {
stuName = name;
deptCode = dCode;
stuCode = sCode;
}
}
package cn.daniel.tedu;
public class TestLei {
public static void main(String[] args) {
schools.Student[] s = new schools.Student[5];//使用Student类的全名
for (int i = 0; i < s.length; i++) {
s[i] = new schools.Student("A"+ i, 100+i, 10+i);
System.out.println(s[i].stuName+" "+ s[i].stuCode+" "+s[i].deptCode);
}
}
}
运行结果:
A0 100 10
A1 101 11
A2 102 12
A3 103 13
A4 104 14
2、导入需要使用的类
package xlyDay01;
import java.util.Scanner;//导入需要使用的包
public class Demo04 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int score = reader.nextInt();//从键盘读取成绩
switch (score/10) {
case 9:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
System.out.println("C");
break;
case 6:
System.out.println("D");
break;
}
}
}
在程序中可以根据需要编写多个import语句,但必须位于package语句之后,class语句之前
3、导入整个包
某些情况下,在同一个源文件里面需要使用同一个包中的很多类,这是可以选择导入整个包。这样就可以把这个包中所有的类全部加载到文件中。
写法:
import java.lang.*;
import java.util.*;
等等
注意:
包具有分级结构,java 包与 java.lang 包是包含关系,import.java.* 只导入了java包中所有的类,但不会导入 java.lang 包中的类。如果需要引入 java.lang 中的类,需要重新编写import语句。
(四)文件打包
Java程序在运行时,需要将使用到的类的字节码加载到内存。可以使用jar.exe命令把一些类的字节码文件压缩成一个JAR文件,然后将JAR文件存放到Java运行环境的扩展中,即将该JAR文件放在JDK安装目录的jre\lib\ext文件夹中。这样就可以使用JAR文件中的类来创建对象了。
1、将应用程序压缩成JAR文件
假设程序中有两个类:First和Second,其中First是主类,生成一个JAR文件的步骤如下:
编写清单文件manifest.mf
Manifest-Version: 1.0
Class: First Second
Created-By: 1.6
注意:编写清单文件时 “ : “ 右侧必须有且只有一个空格
生成JAR文件
jar 的命令语法为:jar { ctxuf} [ vme0Mi ] [ -C 目录 ] 文件名…
参数含义表:
参数 | 含义 |
---|---|
-c | 创建新的归档文件 |
-t | 列出归档目录 |
-x | 解压缩已归档的指定(或所有)文件 |
-u | 更新现有的归档文件 |
-v | 在标准输出中生成详细输出 |
-f | 指定归档文件名 |
-m | 包含指定清单文件中的清单信息 |
-e | 为捆绑到可执行JAR文件的独立应用程序指定应用程序入口点 |
-0 | 仅存储:不使用任何ZIP压缩 |
-M | 不创建条目的清单文件 |
-i | 为指定的JAR文件生成索引信息 |
-C | 更改为指定的目录并包含其中的文件 |
2、更新、查看JAR文件
可以使用参数 t 和 f 查看一个JAR文件中的内容,如:
jar -tf Test.jar
使用参数 x 和 f 解压JAR文件:
jar -xf Test.jar
使用 u 和 f 更新一个JAR文件时,例如将一个 Third.class 文件增加至 Test.jar 中的命令为:
jar -uf Test.jar Third.class
七、访问权限
(一)类成员的访问权限
类成员包括成员变量和方法,类的每个成员都可以访问控制修饰符进行定义,用来保护类成员变量。
访问控制形式 | 访问修饰符 | 同一个类 | 同一个包 | 不同包的子类 | 不同包的非子类 |
---|---|---|---|---|---|
公有的 | public | 可以 | 可以 | 可以 | 可以 |
保护的 | protected | 可以 | 可以 | 可以 | |
缺省的 | 无 | 可以 | 可以 | ||
私有的 | private | 可以 |
类的每个成员变(变量、方法、内部类)都可以定义自己的访问权限,但最多只能使用一个访问修饰符,并且访问修饰符必须在其他修饰符之前。
注意:修饰符不能修饰局部变量
1、private修饰符
private修饰的成员变量和方法仅能在其类的方法种被访问,其他类无法直接访问。
但是可以定义一些get/set方法或其他的方法间接访问这些私有成员变量
如果类不可以访问,则其成员变量也不可访问,因此讨论类成员的访问控制的前提必须是类可以访问的
2、无修饰符
如果成员变量没有指定任何的访问修饰符,则表示该成员具有缺省的访问权限,说明类成员的可访问性是友好的,此时只要是同一个包中的其他类都可以访问它。但是对于包外的所有类来说,该成员如同被指定为私有的一样不得访问。
3、protected修饰符
表示成员的访问权限在同一个包的其他类及其子类(可以属于其他包)中。protected将其访问权限扩展到其子类,子类与父类关系更紧密一些,所以在访问权限上,子类可以比其他不相干的类享有更多的权利。
4、public修饰符
表示类成员是公有的,可以被所有类访问。虽然使用方便,不受限制,但是不能滥用。
(二)类的访问权限
类的访问权限有两种:公有类和友好类
类声明时,如果在关键字前面加上public关键字,这样的就是公有类。例如:
public class Student{ }
可以在其他的任何一个类中,使用public类创建对象。如果一个类不加public修饰,就称这样的类是友好类,例如:
class Student{ }
若在另外一个类中使用友好类创建对象,则必须保证他们在同一个包中
还没有评论,来说两句吧...