面向对象
面向对象的概念及特性
面向对象是一种符合人类思维习惯的编程思想,现实生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系。在程序中使用对象来映射现实中的事物,使用对象的关系来描述事物之间的联系,这种思想就是面向对象。
面向对象编程(Object Oriented Programming,简称OOP)是一种程序设计的思想,它把真实世界中的事物抽象为对象,并通过封装、继承、多态等特性来描述对象之间的关系和行为。
面向对象编程的主要特性包括:
1.封装(Encapsulation):将数据和操作数据的方法封装在一起,形成一个“黑盒子”,只对外公开一些必要的接口,隐藏其它细节信息,保证数据的安全性和一致性。
2.继承(Inheritance):子类可以继承父类的属性和方法,通过继承实现代码的重用,提高代码的可维护性和可扩展性。
3.多态(Polymorphism):同一类型的对象在不同的情况下会有不同的行为表现,即一个对象可以以多种形态存在,它可以是父类的对象,也可以是子类的对象,提高了代码的灵活性和可扩展性。
通过以上特性,面向对象编程可以将复杂的问题分解为一个个简单的对象,让程序设计更加模块化、结构化和易于理解,提高了代码的可读性、可维护性和可复用性。
类与对象
类的定义
对象的创建与使用
在Java中,对象的创建与使用需要进行以下步骤:
1.定义类:首先需要定义一个类,包括类名、属性和方法。
2.创建对象:使用“new”关键字创建一个对象,格式为“类名 对象名 = new 类名()”。
3.调用属性和方法:通过对象名来访问属性和方法。属性的访问使用“对象名.属性名”的格式,方法的访问使用“对象名.方法名()”的格式。
例题代码:
public class Car {
String color;
int speed;
public void run() {
System.out.println("Car is running");
}
}
public class Main {
public static void main(String[] args) {
Car car1 = new Car(); // 创建对象
car1.color = "Red"; // 访问属性
car1.speed = 60;
car1.run(); // 调用方法
Car car2 = new Car();
car2.color = "Blue";
car2.speed = 80;
car2.run();
}
}
上面的代码定义了一个Car类,有color和speed两个属性,以及run方法。在Main类中创建了两个Car对象,分别为car1和car2,并给它们的属性赋值。然后调用了Car类的run方法。
通过这个例子可以看出,创建对象需要通过new关键字来完成,访问对象的属性和方法需要使用对象名来调用。
类的设计
类的设计是指根据需求和问题定义类的属性和方法,以实现类的功能。类的设计需要考虑以下几个方面:
1.功能需求:定义类的属性和方法,以实现功能需求。
2.类的可维护性:考虑类的可维护性,包括类的内部实现是否清晰易懂,方法是否命名合理,是否有必要进行抽象等。
3.类的扩展性:考虑类的扩展性,包括类的属性和方法是否可以方便地进行扩展,是否可以应对未来需求的变化。
4.类的重用性:考虑类的重用性,包括是否可以方便地被其他程序模块调用,并且可以适应不同的需求。
5.类的安全性:考虑类的安全性,包括是否可以防止不合理的访问和操作,是否可以保护程序的数据安全。
在进行类的设计时,需要根据需求进行灵活的思考和实践,通过不断地修改和完善来达到一个较为完美的类设计。
类的封装
Java的封装是一种面向对象编程的特性,它允许将对象的状态和行为隐藏在对象内部,对外只暴露必要的接口供其他对象访问。这种将对象的状态和行为封装起来的特性被称为信息隐藏或数据隐藏。
在Java中,封装是通过访问修饰符来实现的。通过将属性设置为private,可以将其隐藏在对象内部,防止外部对象直接访问和修改属性的值。而公共的方法可以被其他对象访问,通过这些方法可以访问和修改对象的私有属性,同时还可以对方法进行控制,确保对象状态的合法性和安全性。
Java的封装有助于保护对象的状态不被意外修改,同时也提高了对象的安全性和可维护性。通过封装,对象的实现细节被隐藏起来,使得对象的使用者只需关注对象提供的接口,而无需关心对象内部的具体实现。这使得程序更加模块化,易于维护和扩展。
任务1超市购物程序设计
构造方法的定义
类的构造方法是用于创建对象时被调用的特殊方法,它的名称必须与类名相同,没有返回值类型,并且不能被直接调用。构造方法的主要作用是在对象创建时为对象的成员变量初始化。
构造方法有以下特点:
1.构造方法名必须和类名相同,且没有返回值类型声明。
2.可以有多个构造方法,只要它们的参数列表不同(即构成重载)。
3.如果类没有定义构造方法,Java编译器会默认生成一个无参的构造方法。
4.构造方法可以被重载,即在同一个类中可以有多个构造方法,只要它们的参数列表不同即可。
构造方法的重载
构造方法重载是指在一个类中定义多个构造方法,它们的方法名相同但是参数列表不同,以便创建对象时可以根据不同的参数列表选择不同的构造方法来完成对象的初始化。
构造方法重载的主要目的是为了方便对象的创建,不同的构造方法可以接受不同的参数列表,以适应不同的使用场景。在Java中,每个类都有至少一个构造方法,如果我们没有定义构造方法,编译器会自动生成一个默认的无参构造方法。如果我们自定义了构造方法,那么默认的无参构造方法就不再被自动创建,需要手动定义。
public class Person {
private String name;
private int age;
// 无参构造方法
public Person() {
}
// 带一个参数的构造方法
public Person(String name) {
this.name = name;
}
// 带两个参数的构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getter和setter方法
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;
}
}
this关键字
this 是一个关键字,用于在一个类的方法中引用当前对象,即该方法被调用时正在操作的对象。this 关键字可以用于访问当前对象的成员变量、成员方法和构造方法。
1.访问成员变量
在方法内部,如果局部变量和成员变量同名,那么使用 this 关键字可以访问成员变量。例如:
public class Person {
private String name;
public void setName(String name) {
this.name = name; // 使用 this 访问成员变量 name
}
}
2.调用成员方法
在一个成员方法中,可以使用 this 调用当前对象的其他成员方法。例如:
public class Person {
public void sayHello() {
System.out.println("Hello!");
}
public void greet() {
this.sayHello(); // 调用当前对象的 sayHello 方法
}
}
3.调用构造方法
在一个构造方法中,可以使用 this 调用当前类的其他构造方法。例如:
public class Person {
private String name;
private int age;
public Person() {
this("Unknown", 0); // 调用另一个构造方法
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
垃圾回收
在Java中,对象的销毁是由Java虚拟机自动完成的,无需程序员手动销毁。Java虚拟机在内存管理中使用垃圾回收机制,当一个对象不再被任何引用变量所引用时,Java虚拟机会自动回收该对象所占用的内存空间。也就是说,当程序中没有任何引用变量指向某个对象时,该对象就成为无用对象,等待被垃圾回收器回收。
在垃圾回收的过程中,Java虚拟机会标记所有被引用的对象,并将其保留在内存中,而未被引用的对象会被回收。Java虚拟机会定期执行垃圾回收,以便回收无用对象,释放内存空间。在对象销毁时,Java虚拟机会自动调用对象的finalize()方法,该方法可以在对象被销毁前进行一些必要的清理工作,例如关闭文件、释放网络资源等。
需要注意的是,虽然Java虚拟机自动进行内存管理,但是如果程序员在代码中使用了大量的无用对象,会导致垃圾回收频繁执行,从而影响程序的性能。因此,程序员需要注意控制对象的创建和销毁,尽量避免产生过多的无用对象。可以通过使用对象池、对象复用等技术来降低对象的创建和销毁次数,从而提高程序的性能。
static关键字
static 是 Java 中的一个关键字,用于表示静态的意思。在 Java 中,static 通常可以用来修饰以下内容:
静态变量:使用 static 关键字修饰的变量称为静态变量,也叫类变量。静态变量属于类,而不是属于对象,因此只会被创建一次,并且可以被所有对象所共享。静态变量可以通过类名直接访问,也可以通过对象名访问。
静态方法:使用 static 关键字修饰的方法称为静态方法,也叫类方法。静态方法属于类,而不是属于对象,因此可以直接通过类名调用,而不需要创建对象。静态方法只能访问类的静态变量或其他静态方法,而不能访问类的非静态成员变量或非静态方法。
静态代码块:使用 static 关键字定义的代码块称为静态代码块。静态代码块在类加载时执行,且只执行一次,通常用来初始化类的静态变量。
静态内部类:使用 static 关键字修饰的内部类称为静态内部类。静态内部类可以像静态变量一样被类的所有对象所共享,并且可以直接通过类名来创建对象。
使用 static 可以使代码更加简洁、高效,也可以用于实现单例模式等设计模式。但是,在使用 static 时需要注意避免静态变量的重复赋值和静态方法的滥用,否则可能会造成程序的不稳定性和安全性问题。
成员内部类
类的继承
继承的概念
继承是面向对象编程中的一个重要概念,指的是在一个类中定义另一个类,并使得新定义的类具有被继承类的属性和方法。被继承的类称为父类或超类,新定义的类称为子类或派生类。
通过继承,子类可以获得父类中定义的属性和方法,包括公共、受保护和包访问权限的属性和方法。子类可以覆盖或重写父类中的方法,并可以添加新的属性和方法,以扩展或修改父类的行为。
继承提高了代码的重用性和可维护性,同时也允许我们使用多态来实现更灵活的程序设计。继承是面向对象编程中的一项基本技术,被广泛应用于软件开发领域。
Java中的类可以通过继承来获得另一个类的属性和方法。继承可以使代码重用性更好,也可以使代码更加灵活和可维护。
在Java中,一个类可以通过extends关键字来继承另一个类。被继承的类称为父类,继承它的类称为子类。
在Java语言里,一个类继承另一个类需要用到关键字extends,关键字extends的使用方法如下:
class Child extends Parent{ }
因为Java只支持单继承,即一个类只能有一个父类,所以以下代码是错误的:
class Child extends Parent1,Parents2{ }
重写父类方法
super关键字
super是Java中的一个关键字,可以用来访问父类中的成员变量和成员方法。在子类中,如果成员变量或成员方法与父类相同,可以使用super关键字来区分调用的是父类的还是子类的。
super的常见用法有:
调用父类的构造方法:可以使用super()来调用父类的构造方法,以便初始化父类的成员变量。通常在子类的构造方法中使用。
调用父类的成员方法:可以使用super.methodName()来调用父类的成员方法,以便实现父类的功能或者扩展父类的功能。
访问父类的成员变量:可以使用super.variableName来访问父类的成员变量,以便获取或者修改父类的状态。
需要注意的是,super只能访问父类的成员,无法访问祖先类或其他类的成员。另外,使用super关键字来调用父类的方法或者访问父类的成员变量,必须在子类中进行。
final关键字
final 是 Java 中的一个关键字,可以用来修饰类、方法和变量。使用 final 修饰的类不能被继承,使用 final 修饰的方法不能被子类重写,使用 final 修饰的变量不能被修改。
在Java中,使用final关键字来修饰变量,表示该变量的值不可被修改。final变量可以在声明时初始化,也可以在构造函数中初始化,但是在程序运行期间,它的值不能再被修改。
一般来说,final变量的命名全部大写,用下划线分隔,例如MAX_VALUE。
final变量的特点:
1.一旦被赋值,就不能再次修改
2.必须在声明时或在构造函数中赋初值
3.在方法中声明的final变量在方法结束时就被销毁
4.final变量的值不能被修改,但它所引用的对象内部的状态可以改变
final变量的作用:
1.保证常量的值不会被修改
2.避免因为修改常量的值导致程序出现错误
3.提高代码的可读性和可维护性
4.在编译器优化时会被作为常量直接替换掉,提高程序的执行效率
抽象类和接口
抽象类
在解决实际问题时,一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。回想继承和多态原理,继承树中越是往上的类越抽象,如鸽子类继承鸟类,鸟类继承动物类等。在多态机制中,并不需要将父类初始化为对象,我们需要的只是子类对象,所以在Java语言中设置抽象类不可以实例化对象。
接口
接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。对于上面的问题,可以将draw()方法封装到一个口袋中,使需要draw()方法的类实现这个接口,同时继承图形类,这就是接口存在的必要性。
Java中,接口通过关键字“interface”来定义,接口中的方法默认是public abstract类型的,常量是public static final类型的。接口可以被类实现(implements),表示类遵循了该接口的规范,同时必须实现该接口中定义的所有抽象方法。语法如下:
public interface Paintable{
void draw(); //定义接口方法可省略public abstract关键字
}
一个类可以实现多个接口,但只能继承一个父类。这使得接口成为了Java中实现多继承的一种方式。通过实现多个接口,一个类可以拥有多种类型的行为特征。
接口也可以继承(extends)其他接口,这使得接口可以通过继承机制扩展接口的行为特征。当一个接口继承了另一个接口时,它将自动包含另一个接口中的所有常量和方法定义。
总之,接口提供了一种机制,用于定义类的一组操作行为,并将这些行为规范化,以便在实现类中实现具体的操作行为。
多态
多态概念
多态(Polymorphism)是面向对象编程中的一个重要概念,指同一种类型的对象,在不同的情况下有不同的表现形式和行为。
具体来说,多态是指一个父类引用指向子类对象,根据实际所指向的子类对象的类型不同,同一种方法可能会有不同的表现形式和行为。例如,一个名为Animal的父类中有一个方法makeSound(),分别有子类Cat和Dog继承自该父类,并分别重写了makeSound()方法。那么,当父类引用指向Cat对象时,调用makeSound()方法输出"喵喵喵",而当父类引用指向Dog对象时,调用makeSound()方法输出"汪汪汪"。
多态有助于增加代码的灵活性和扩展性,使得程序的可维护性和可扩展性更高。
多态的类型转换
多态的类型转换主要包括向上转型和向下转型。
1.向上转型(upcasting):将子类对象赋值给父类引用变量。向上转型是自动进行的,不需要进行任何操作,例如:
Animal animal = new Cat();
在这个例子中,子类 Cat 对象被赋值给了父类 Animal 的引用变量 animal,这个过程是自动的。
2.向下转型(downcasting):将父类对象强制转换成子类对象。向下转型需要使用强制类型转换符,例如:
Animal animal = new Cat();
Cat cat = (Cat) animal;
在这个例子中,先将子类 Cat 对象赋值给父类 Animal 的引用变量 animal,然后通过强制类型转换符将 animal 强制转换成子类 Cat 的引用变量 cat。需要注意的是,如果父类对象不是子类对象,这个转换将会导致运行时错误。因此,在进行向下转型时,需要使用 instanceof 运算符进行类型检查,以避免运行时错误的发生。
Object类
在Java中,所有的类都默认继承自Object类,因此Object类是Java中最基本的类之一。Object类中定义了一些基本的方法,其他所有的类都可以使用这些方法,也可以重写这些方法来满足自己的需求。
1.getClass()方法
getClass()方法是Object类中的一个方法,它返回一个对象的运行时类型的Class对象。Class对象包含了该对象的类的相关信息,比如类的名称、类的修饰符、类的父类、类的实现的接口等等。
getClass()方法的使用场景比较广泛,例如在反射中,我们可以使用getClass()方法获取一个对象的Class对象,进而通过反射来获取该类的各种信息,比如构造方法、成员变量、成员方法等等。
getClass方法语法如下:
getClass().getName();
可以将getClass()方法与toString()方法联合使用
2.toString()方法
toString()方法是object类中的一个方法,用于返回对象的字符串表示形式。它的作用是将对象转换为字符串,方便打印和调试。
在Java中,所有的类都继承自Object类,如果一个类没有自己实现toString()方法,则默认继承Object类的toString()方法。这个默认的toString()方法返回一个字符串,包含该对象所属类的名称和对象的哈希码。
如果要自定义toString()方法,可以在类中重写该方法,并返回一个适当的字符串,用于表示该对象的状态。这样可以使得打印对象时输出的内容更加有意义。
3.equals()方法
在Java中,equals()是Object类中的方法,它的作用是用于比较两个对象是否相等。在默认情况下,equals()方法与“==”运算符的作用相同,即比较两个对象的引用是否相等,两者的区别在于“==”比较的是两个对象引用内存地址是否相等,而equals()方法比较的是两个对象的实际内容。如果我们想要比较两个对象的内容是否相等,就需要重写equals()方法。
匿名内部类
Java中的匿名内部类是一种特殊的内部类,它没有类名而是直接使用new关键字创建,通常用于创建临时的、一次性的类。匿名内部类常常用于实现接口或抽象类中的方法。
匿名内部类是一种没有名字的局部内部类,用于创建只需要一次使用的类。通常用来简化代码,避免编写繁琐的类定义。匿名内部类通常用于实现接口或者继承抽象类,并重写其中的方法,同时还可以在内部定义成员变量和方法。匿名内部类可以在创建对象的同时定义类的内容,并返回该对象的引用。
匿名内部类的语法格式如下:
new 父类构造器|实现接口(){
//匿名内部类的类体部分
};
其中父类构造器可以是有参构造器,也可以是无参构造器;实现接口可以是单个接口或者多个接口,使用逗号分隔。匿名内部类创建对象时,需要调用父类构造器或实现接口的方法,因此匿名内部类不能有显式的构造器。
任务2 模拟物流快递系统程序设计
结束力,别问,问就是摆。