四、面向对象(上)
01.基本概念:
- 面向对象是一种编程思想,一种思考问题的思维方式;
- 建立面向对象思维方式:
2.1 先整体,再局部;
2.2 先抽象,再具体; - 对比:
3.1 面向过程:以步骤为单位,一步一步完成某个具体事情;
3.2 面向对象:以对象为单位,通过调度组合不同的对象来完成某件事。
02.类和对象
- 类:分类、类别,通过分类,区分不同的事物种类;所以类是一组具有相同特性(属性)与行为(方法)的事物的集合;
- 类和对象的关系:
2.1 类表示一个共性的产物,是一个综合的特征;
2.2 对象是一个个性的产物,是一个个体的特征;
2.3 类由属性和方法组成,属性就相当于一个个的特征,方法就相当于一个个的行为; - 定义方式:
3.1 class+类名称{ },类名称 对象名称=new 类名称();
3.2 一个类想要真正的进行操作,则必须依靠对象;
3.3 访问类中的属性和方法:对象.属性,对象.方法();
3.4 class Horse{Horse h=new Horse();h.run();new Horse.eat()(匿名对象);}
3.5 匿名对象:只能使用一次,用完后,该对象就会被释放;
3.6 释放对象:h=null,堆内存中的对象没有栈中的引用指向时,会被GC回收。 - 小结:
03.封装性
- 概念:隐藏实现细节,仅对外提供访问接口;
- 优点:
2.1 模块化;
2.2 信息隐藏;
2.3 代码重用;
2.4 插件化易于调试;
2.5 具有安全性; - 缺点:影响程序执行效率;
- 实现:private关键字修饰属性和方法,提供public共有的方法间接访问;
- 成员变量和局部变量:
5.1 类中的位置不同: 成员变量书在类中定义的变量,局部变量是在方法中定义的变量;
5.2 内存中的位置不同:成员变量属于对象,进堆内存;局部变量属于方法,进栈内存;
5.3 生命周期不同:成员变量随着对象的创建而存在,随着对象的销毁而消失;局部变量随着方法的调用而存在,方法调用完毕消失;
5.4 初始化值不同:成员变量有默认初始化值,引用类型默认为null;局部变量没有默认初始化值,必须定义、赋值。
04.构造方法
- 定义:类构造对象时调用的方法,用于对象的初始化,是实例化(new创建)一个类的对象最先调用的方法;
- 定义格式:方法名称与类名称相同,无返回值类型;
- 构造方法重载:无参构造方法、带参构造方法;
- 小结:
- this关键字:
5.1 调用类中的属性;
5.2 调用类中的方法或构造方法;
5.3 表示当前对象; - 值传递与引用传递:
/**
示例一:值传递
*/
public class Test1 {
public static void main(String[] args) {
int x=10;
method(x);
//基本数据类型直接赋值,跟堆没关系,输出仍然是10
System.out.println("x="+x);
}
public static void method(int mx) {
mx=20;
}
}
/**
示例二:引用传递
*/
public class Test2 {
public static void main(String[] args) {
int x=10;
Duck d=new Duck();
method(d);
//duck,d都存的一样的内存地址,都指向同一个堆内存对象,修改了age的值
System.out.println("Duck age="+d.age);
}
public static void method(Duck duck) {
duck.age=5;
}
class Duck{
int age=2;
}
}
- static关键字:
7.1 修饰属性,实质上就是全局变量;
7.2 修饰方法,无需本类的对象即可调用此方法;
7.3 修饰一个类(内部类); - 声明static方法限制:
8.1 仅能调用其他static方法;
8.2 只能访问static数据;
8.3 不能以任何方式引用this或super。
05.代码块
- 普通代码块:直接写在方法中的代码块;
public class Test {
public static void test() {
{//普通代码块,限制作用域
int i=10;
System.out.println(i);
}
}
}
- 构造块:在类中定义的代码块,在创建对象时被调用,优于构造方法执行;
public class Test {
{//构造块
System.out.println("构造块");
}
}
- 静态代码块:在类中使用static声明的代码块,在第一次创建对象时被调用,只会执行一次,优于构造块执行,一般用来初始化只调用一次的数据;
public class Test {
static{
System.out.println("静态代码块");
}
}
- 同步代码块:多线程时讲解;
- 重点:使用的顺序:静态代码块、普通代码块、同步代码块、构造代码块。
06.单例设计模式
- 保证一个类仅有一个实例,并提供一个访问它的全局访问点;
1.1 构造方法私有化;
1.2 声明一个本类对象;
1.3 给外部提供一个静态方法获取对象的实例; - 两种实现方式:
2.1 饿汉式:在类被加载后,对象被创建;
2.2 懒汉式:在第一次调用get方法时,对象被创建;
/**
1.饿汉式:占用内存时间长,提高效率
*/
public class Singleton1 {
private Singleton1() {};
private static Singleton1 s = new Singleton1();
public static Singleton1 getInstance {
return s;
}
}
/**
2.懒汉式:占用内存时间短,效率稍低
*/
public class Singleton2 {
private Singleton2() {};
private static Singleton2 s;
public static Singleton2 getInstance {
if(s==null){
s=new Singleton2();
}
return s;
}
}
- 优点:
3.1 在设计一些工具类的时候使用单例设计模式(通常工具类,只有功能方法,没有属性);
3.2 工具类可能被频繁调用;
3.3 节省重复创建对象所带来的内存消耗,提高效率;
07.对象数组案例
对象数组与管理:使用对象数组实现多个Chicken的管理;
// 需要管理的对象
public class Chicken {
private int id;
private String name;
private int age;
public Chicken() {}
public Chicken(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void print() {
System.out.println("Chicken [id=" + id + ", name=" + name + ", age=" + age + "]");
}
}
// 对象数组管理
import java.util.Arrays;
public class ChickenManager {
private Chicken[] cs = null;
private int count = 0;
public ChickenManager(int size) {
if (size > 0) {
cs = new Chicken[size];
} else {
cs = new Chicken[5];
}
}
// 实现动态数组
// 添加
public void add(Chicken c) {
if (count >= cs.length) {
int newLength = cs.length * 2;
cs = Arrays.copyOf(cs, newLength);
}
cs[count] = c;
count++;
}
// 删除
public void delete(int id) {
for (int i = 0; i < count; i++) {
if (cs[i].getId() == id) {
for (int j = i; j < count - 1; j++) {
cs[j] = cs[j + 1];
}
cs[count - 1] = null;
count--;
break;
}
}
}
// 更新
public void update(Chicken c) {
Chicken temp = find(c.getId());
if (temp != null) {
temp.setName(c.getName());
temp.setAge(c.getAge());
}
}
// 查找
public Chicken find(int id) {
for (int i = 0; i < count; i++) {
if (cs[i].getId() == id) {
return cs[i];
}
}
return null;
}
public void printAll() {
for (int i = 0; i < count; i++) {
cs[i].print();
}
}
public int length() {
return cs.length;
}
}
//测试
public class ChickenTest {
public static void main(String[] args) {
ChickenManager cm = new ChickenManager(5);
//动态数组,可添加超过原始数组长度
cm.add(new Chicken(1,"小小",10));
cm.add(new Chicken(2,"小一",2));
cm.add(new Chicken(3,"小二",8));
cm.add(new Chicken(4,"小三",6));
cm.add(new Chicken(5,"小四",12));
cm.add(new Chicken(6,"小五",5));
cm.add(new Chicken(7,"小六",4));
//打印所有
System.out.println("-----打印所有-------");
cm.printAll();
//查找
System.out.println("-----查找-------");
cm.find(3).print();
//更新
cm.update(new Chicken(1,"下蛋公鸡",9));
System.out.println("-----更新打印-------");
cm.printAll();
//删除
cm.delete(3);
System.out.println("-----删除打印-------");
cm.printAll();
cm.find(1).print();
System.out.println(cm.length());
}
}