二、面向对象--1
(一)软件开发概述
112、软件生命周期和软件设计原则
(二)软件开发方式
113、软件设计之面向过程
114、软件设计之面向对象
(三)类和对象
115、理解什么是抽象
116、类和对象的关系
117、类的定义
[修饰符] class 类名
{
0~N个成员变量(字段/field),不要叫属性(JavaBean中的特殊的一种成员)
0~N个方法
}
--------------------------------------------------------------------------
定义类的注意:
1)如果类使用了public修饰符,必须保证当前文件名称和当前类名相同
2)类名使用名称表示,类表示某一类事务,首字母大写,如果是多个单词组成使用驼峰表示法
3)在面对对象的过程中,定义类的时候,专门为描述对象提供一个类,该类不需要main方法,专门再定义一个测试类/演示类来运行程序
//菲佣类型,描述菲佣对象:包括菲佣的状态和行为
class Servant
{
String name; //成员变量:姓名
int age; //成员变量:年龄
void shopping();
{
System.out.println("买菜......");
}
void cook();
{
System.out.println("做饭......");
}
void wash();
{
System.out.println("洗碗......");
}
}
118、对象的创建和调用方法以及操作字段
1)根据类来创建对象的语法:
类名 变量 = new 类名();
2)给字段设置值:
对象变量.字段名 = 该类型的值;
3)获取字段的值:
该字段类型 变量 = 对象变量.字段值;
4)通过对象调用方法
对象变量。方法(实参);
//菲佣类型,描述菲佣对象:包括菲佣的状态和行为
class Servant
{
String name; //成员变量:姓名
int age; //成员变量:年龄
void shopping()
{
System.out.println("买菜......");
}
void cook()
{
System.out.println("做饭......");
}
void wash()
{
System.out.println("洗碗......");
}
}
//程序员
class Coder
{
void coding()
{
System.out.println("写代码......");
}
}
//Servant的测试类
public class ServantDemo
{
public static void main(String[] args)
{
//创建一个菲佣对象
Servant s1 = new Servant(); // s1表示Servant的对象
//给菲佣s1起名和设置年龄
s1.name = "肖丽";
s1.age = 18;
System.out.println(s1.name + "," + s1.age);
//调用肖丽的买菜,做饭,洗碗功能
s1.shopping();
s1.cook();
s1.wash();
//调用程序员写代码的功能
//创建Coder的对象,来写代码
Coder c1 = new Coder();
c1.coding();
}
}
119、对象的实例化过程
成员变量有初始值
局部变量没有初始值,使用前需要先初始化
120、打印和比较对象-对象生命周期-匿名对象
1)对象的打印操作:打印对象的效果,如:Servant@1db9742
类的名称@十六进制的hashcode
其实我们打印对象,关心的是对象的数据是多少,讲解Object的toString方法
2)对象的比较操作: ==:对于基本数据类型来说,比较的是值,对于引用数据类型来说,比较的是在内存中的值
每次使用new关键字,都表示在堆值新开辟一块内存空间,不同的内存空间,地址值不同
需求:想要两个对象拥有完全相同的数据,要让他们相同,讲解Object的equals方法
3)对象的生命周期:
使用new关键字的时候,就会在内存开辟新的空间,此时对象开始存在;
当堆中的对象没有被任何变量所引用,此时该对象就成了垃圾,就等着GC来回收该垃圾,当被回收的时候,对象就被销毁了。回收垃圾的目的是释放更多的内存空间
4)匿名对象:没有名称的对象,创建对象之后,没有赋给某一个变量,
如:new Servant(); //匿名对象,只是在堆中开辟一块新的内存空间,但是没有把该空间地址赋给任何变量
因为没有名称,匿名对象仅仅只能使用一次;一般把匿名对象作为方法的实参传递
121、学生缴学费案例
//学生缴学费案例
//定义一个学生的类,描述学生对象
class Student
{
String name; //学生的姓名,默认值null
boolean isFee = false; //学生的缴费状态,默认值false
void fees()
{
isFee = true; //设置为已经缴费
}
}
public class StudentDemo
{
public static void main(String[] args)
{
//创建4个学生对象
Student s1 = new Student();
s1.name = "赵一";
s1.isFee = true;
Student s2 = new Student();
s2.name = "倩儿";
Student s3 = new Student();
s3.name = "孙三";
s3.isFee = false;
Student s4 = new Student();
s4.name = "李四";
s4.isFee = true;
//创建一个数组用于存储所有的学生对象 数组元素类型[] arr = new 数组元素类型[] {s1,s2,s3,s4};
Student[] arr = new Student[] {s1,s2,s3,s4};
//使用循环迭代数组中的每一个元素
for (Student ele: arr ) 数组数据类型 变量名 : 数组名 ;
{
System.out.println(ele.name +"," + ele.isFee); // 打印出当前学生缴费情况
//判断当前学生状态是否缴费,如果没有,则调用缴费方法
if (!ele.isFee)
{
ele.fees();
}
}
for (Student ele: arr )
{
System.out.println(ele.name +"," + ele.isFee); // 打印出调用缴费方法后学生缴费情况
}
}
}
(四)构造器
122、构造器概述和缺省构造器
创建一个学生对象,代码如下:
Student s1 = new Student(); //像在调用Student的无参数方法
把这种特殊的方法称之为构造方法/构造器(构造函数/构造字:constructer)
但是在Student类中却找不到该构造方法,找不到,却又没有报错。编译器在编译源文件的时候,会默认创建一个缺省的构造器
构造器的作用:
1)创建对象,必须和new一起使用
2)完成对象的初始化操作
构造器的特点:
1)构造器的名称和当前所在类的名称相同
如果构造器名称叫XXX,new XXX(); 看不出来创建的是什么类型的对象
2)禁止定义返回类型,不要使用void作为返回类型,void Student(){}是普通方法
假设需要返回类型,也该这样写:Student Student(); 既然所有的返回类型都和所在类名相同,又何必再写
3)在构造器中,不需要使用return语句。
构造器本身是有返回的,返回的是当前创建对象的应用
编译器创建的默认构造器的特点:
1)符合构造器的特点
2)无参数的
3)无方法体
4)如果类A没有使用public修饰,则编译器创建的构造器也没有public修饰;如果类A有使用public修饰,则编译器创建的构造器也有public修饰
如果我们没有显示提供构造器,则编译器在编译时会创建一个缺省的构造器;如果我们显示定义了构造器,则编译器不再创建默认构造器
一个类至少有存在一个构造器
123、自定义构造器和构造器重载
//演示自定义构造器
class Person
{
//自定义构造器
Person()
{
System.out.println("Hello World!");
}
}
class Person1
{
Person1(String n)
{
System.out.println(n);
}
}
class PersonDemo
{
public static void main(String[] args)
{
//创建对象,其实是在调用构造器
new Person(); //表示调用Person类中无参数的构造器
new Person1("Hello World!"); //表示调用Person1类中,带有一个String类型的参数的构造器
}
}
//演示自定义构造器中初始化
class Person
{
String name = null; //人的参数
Person(String n)
{
name = n; //把n参数的值赋给name字段
//初始化操作,可以给字段设置初始值,也可以调用初始化方法
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person("Hello World!"); //表示调用Person类中,带有一个String类型的参数
System.out.println(p.name);
}
}
方法的重载:避免在同一个类中,相同功能的方法名字不同的问题。判断依据:两同一不同
构造器是一种特殊的方法,也可以存在重载。
//演示自定义构造器
class Person
{
//自定义构造器
Person()
{
System.out.println("Hello World!");
}
Person(String n)
{
System.out.println(n);
}
}
class PersonDemo3
{
public static void main(String[] args)
{
//创建对象,其实是在调用构造器
new Person(); //表示调用Person类中无参数的构造器
new Person("Hello World!"); //表示调用Person1类中,带有一个String类型的参数的构造器
}
}
(五)static修饰符
124、static修饰符和特点
static修饰符的特点:
1)static修饰的成员(字段/方法),随着所在类的加载而加载。当JVM把字节码加载进JVM的时候,static修饰的成员已经在内存中存在了
2)优先于对象的存在。对象是手动通过关键字new创建出来的
3)static修饰的成员被该类型的所有对象所共享。 根据该类创建出来的任何对象,都可以访问static成员。(狗天生就吃屎)
剧透:表面上通过对象去访问static成员,其本质依然使用类名访问,和对象没有任何关系
4)直接使用类名访问static成员。 static修饰的成员,直接属于类,不属于对象,所以可以直接使用类名访问static成员
125、static成员在JVM中的存储
//人类
class Person
{
String name;
int age;
//不属于某个对象,属于人类
static int totalNum = 5; //人的总人数
Person(String n, int a)
{
name = n;
age = a;
totalNum ++;
}
void die()
{
totalNum --;
System.out.println("去世......");
}
//只有人类才有毁灭
static void destory()
{
totalNum = 0;
System.out.println("人类毁灭......");
}
}
//演示static修饰符
public class PersonDemo
{
public static void main(String[] args)
{
System.out.println("第一次的人数:" + Person.totalNum);
Person p1 = new Person("Will", 15); //创建对象
Person p2 = new Person("Lucy", 18); //创建对象
System.out.println("第二次的人数:" + Person.totalNum);
//System.out.println(p1.totalNum); //表面上是通过对象去访问static成员,其本质依然是使用类名访问,和对象没有任何关系
//System.out.println(p2.totalNum); //和System.out.println(Person.totalNum);访问的结果是一样的
p2.die(); //p2去世
System.out.println("第三次的人数:" + Person.totalNum);
Person.destory(); //人类毁灭
}
}
126、类成员和实例成员的访问
类成员和实例成员的访问:
类中的成员:字段、方法、内部类
类成员:使用static修饰的成员
实例成员:没有使用static修饰的成员
类成员只能访问类成员,实例成员只能访问实例成员
类成员,直接属于类,可以直接通过类来访问static方法;实例成员,只属于对象,通过对象来访问非static字段和非static方法(对象其实可以访问类成员,但底层依然使用类名访问的)
在static方法中只能调用static成员;非static方法可以访问静态成员,也可以访问实例成员(非static成员)
什么时候定义成static的字段和方法?
如果这个状态和行为属于整个事务(类),就直接使用static修饰,被所有对象所共享。在开发中,往往把工具方法使用static修饰,如果不使用static修饰,则这些方法属于该类的对象,我们得先创建对象再调用方法,在开发中工具对象只需要一份即可,可能创建N个对象,此时我们往往把该类设计为单例的,但还是有点麻烦。所以,一般在开发中设计工具方法,为了调用简单,我们使用static修饰
类成员的使用:利处:对对象的共享数据进行单独空间的存储,节省空间,没有必要每个对象中都存储一份,可以直接被类名调用。弊端:生命周期过长
127、小结