Java中的面向对象编程是一种编程范式,它将程序中的数据和操作视为一个相互关联的对象,并通过类、对象、继承、封装、多态等概念来实现。具体来说,Java中的面向对象编程包括以下几个方面:
通过面向对象编程,可以提高代码的可读性、可维护性和可扩展性,使程序更加灵活和易于开发。对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路,来分析整个系统,但是,具体到微观操作,仍然需要面向过程的思路去处理!面向过程思想步骤清晰简单,第一步做什么,第二步做什么…
类是一种模板或蓝图,用于定义对象的属性和方法。相比之下,对象则是类的一个实例,拥有类定义的属性和方法。
具体来说,我们可以将类看做是一个抽象的概念,它包含了一组属性和方法的定义,描述了一个对象所具有的特征和行为。而对象则是这个类的具体实例,拥有类中定义的属性和方法,同时还有自己的状态和行为。
类和对象之间的关系可以用以下几个点来总结:
对象是类的实例。类定义了对象的属性和方法,对象则是该类的一个实例,拥有类的属性和方法。
类是对象的模板。类可以看作是对象的模板或蓝图,它描述了对象的共同属性和行为。
类是抽象的概念。类是一种抽象的概念,它只描述了对象的特征和行为,而不是具体的实例。
对象是具体的实体。对象是具体的实体,它拥有类定义的属性和方法,并具有自己的状态和行为。
总之,类和对象是面向对象编程中最基本的两个概念,理解它们之间的关系对于理解和设计面向对象程序非常重要。
封装是将数据和方法包含在类中,并对外部代码隐藏内部实现细节的机制。通过封装,我们可以将数据和相关的操作封装在一个类中,只对外提供公共接口进行访问。这种方式可以保护数据的安全性并提高代码的可维护性。例如,通过使用private修饰符来限制对类的属性的直接访问,然后提供public方法来控制属性的访问和修改,比如说set,get方法。
高内聚,低耦合
记住这句话: 属性私有,get/set
示例:
Day11607.java
package com.determination;
public class Day11607 {
public static void main(String[] args) {
Student student=new Student();
student.setName("小罗同学");
System.out.println("他是"+student.getName());
}
}
Student.java
package com.determination;
public class Student {
//属性私有
private String name;
private int age;
private char sex;
//提供了一些可以操纵这些属性的方法
public void setName(String name)
{
this.name=name;
}
public String getName() {
return this.name;
}
}
同样使用Alt+Insert,自动生成
总:
继承是指一个类可以从另一个类继承属性和方法。通过继承,子类可以拥有父类的所有数据和方法,并且可以根据需要重写或添加新的方法。继承可以实现代码的重用性和层次化结构,使得类之间的关系更加清晰和灵活。在Java中,使用关键字"extends"来建立类之间的继承关系。
输出结果:
luozhang
wind
lz
Crtl+H
隐藏代码super()这里显示的给出了,也可省略,是一样得结果.
私有的东西无法被继承.
继承具有以下重要的特点:
子类可以继承父类的变量、方法和内部类。
子类可以覆盖(即重写)父类的方法。
子类不能继承父类的构造器,但可以通过 super() 调用父类的构造器。
子类可以定义自己的变量、方法和内部类,这些成员与父类的成员同名时,子类的成员将隐藏父类的同名成员。
子类的实例可以向上转型为父类的类型,这样就可以使用父类的方法和变量了。
在 Java 中,重写(Override)是指子类定义一个与父类具有相同名称、参数列表和返回类型的方法,并且在子类中提供了自己的实现。通过重写,子类可以改变继承自父类的方法的行为,以适应自己的需求。
下面是重写方法的一些要点:
方法签名:重写的方法必须与父类方法具有相同的方法签名,即方法名称、参数列表和返回类型必须完全匹配。
访问修饰符:重写的方法可以具有与父类方法相同或更宽松(即更大范围的可见性)的访问修饰符。例如,如果父类方法是 public,则子类方法可以是 public 或 protected,但不能是 private。
异常:重写的方法可以抛出与父类方法相同的异常或该异常的子类,或者不抛出任何异常。不能抛出比父类方法声明的更多或更宽泛的异常。
调用父类方法:在重写的方法中,如果需要调用父类的方法实现,可以使用 super 关键字。通过 super.methodName() 来调用父类的方法。
总:
重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大,但是不能缩小: public>protected>Default>private
4.抛出的异常:范围,可以被缩小,但不能扩大:classNotFoundException–>Exception(大)
为什么需要重写?
父类的方法字类不需要,或者不一定满足!
class Animal {
public void makeSound() {
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
animal.makeSound(); // 输出:The animal makes a sound
dog.makeSound(); // 输出:The dog barks
}
}
在上述示例中,我们定义了一个 Animal 类和一个 Dog 类,其中 Dog 类继承自 Animal 类并重写了 makeSound() 方法。
在主程序中,我们创建了一个 Animal 对象和一个 Dog 对象,并分别调用它们的 makeSound() 方法。由于 Dog 类重写了父类的方法,因此 dog.makeSound() 的输出是 The dog barks,而不是父类的实现。
需要注意的是,当我们使用 @Override 注解来标记一个方法时,如果方法签名与父类的方法签名不匹配,编译器将引发错误。
几个关键字
public:公共访问级别,是最高级别的访问权限。使用 public 关键字修饰的成员可以被任何类访问,无论是同一个包中的类还是不同包中的类。
protected:受保护访问级别。使用 protected 关键字修饰的成员可以被同一个包中的类访问,也可以被其他包中的子类访问。换句话说,只有当前类、同一个包中的类以及其他包中的子类可以访问。
默认(包访问级别):如果没有明确指定访问权限修饰符,默认的访问权限就是包访问级别。在同一个包中的类可以访问默认访问级别的成员,但是在其他包中的类无法访问。
private:私有访问级别,是最低级别的访问权限。使用 private 关键字修饰的成员只能在当前类内部进行访问,其他任何类都无法访问。
public class MyClass {
public int publicField;
protected int protectedField;
int defaultField; // 默认访问级别,等同于没有明确指定访问权限修饰符
private int privateField;
public void publicMethod() {
System.out.println("This is a public method");
}
protected void protectedMethod() {
System.out.println("This is a protected method");
}
void defaultMethod() {
System.out.println("This is a default method");
}
private void privateMethod() {
System.out.println("This is a private method");
}
}
MyClass 类有四个成员字段和四个成员方法,分别使用了不同的访问权限修饰符。
其他类可以访问 publicField 和 publicMethod(),而 protectedField 和 protectedMethod() 只能在同一个包或其子类中访问。defaultField 和 defaultMethod() 只能在同一个包中访问。而 privateField 和 privateMethod() 只能在当前类内部访问。
通过合理地使用这些访问权限修饰符,我们可以控制类成员的可见性和访问范围,从而保证代码的封装性和安全性。
多态是指同一类型的对象,在不同的情况下会表现出不同的行为。多态分为编译时多态和运行时多态。编译时多态是通过方法的重载实现的,即同一个类中有多个方法名相同但参数列表不同的方法。运行时多态是通过方法的重写和接口实现的,即子类可以重写父类的方法,实现自己特定的行为,或者一个类实现多个接口,提供不同的行为。多态可以提高代码的灵活性和可扩展性,使得程序更具适应性。
在 Java 中,多态(Polymorphism)是指一个对象可以具有多种形态。具体来说,同一个类的不同实例,或不同类之间的实例,可以共享同一种类型或接口,并以各自特定的方式进行操作,多态分为两种类型:编译时多态和运行时多态。
编译时多态也称为静态多态,是指在编译时就能确定变量或表达式的类型,从而确定要调用的方法。在 Java 中,编译时多态主要通过重载实现。重载是指定义了多个方法,它们具有相同的名称但不同的参数列表。
下面是一个示例,展示编译时多态的用法:
class Animal {
public void makeSound() {
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("The dog barks");
}
public void makeSound(int times) {
for (int i = 0; i < times; i++) {
System.out.println("The dog barks");
}
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
animal.makeSound(); // 输出:The animal makes a sound
dog.makeSound(); // 输出:The dog barks
dog.makeSound(3); // 输出:The dog barks The dog barks The dog barks
}
}
我们定义了一个 Animal 类和一个 Dog 类,其中 Dog 类重载了 makeSound() 方法,分别定义了不同的参数列表。
在主程序中,我们创建了一个 Animal 对象和一个 Dog 对象,并分别调用它们的 makeSound() 方法。由于方法的选择是在编译时确定的,因此编译器会根据方法签名选择相应的方法。在这个例子中,animal.makeSound() 调用了父类的实现,输出 The animal makes a sound;dog.makeSound() 调用了子类的实现,输出 The dog barks;dog.makeSound(3) 调用了子类重载的方法,输出 The dog barks The dog barks The dog barks。
运行时多态也称为动态多态,是指在运行时通过实际类型来确定要调用的方法。在 Java 中,运行时多态主要通过继承和重写实现。
下面是一个示例,展示运行时多态的用法:
class Animal {
public void makeSound() {
System.out.println("The animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
animal.makeSound(); // 输出:The animal makes a sound
dog.makeSound(); // 输出:The dog barks
Animal anotherDog = new Dog();
anotherDog.makeSound(); // 输出:The dog barks
}
}
我们定义了一个 Animal 类和一个 Dog 类,其中 Dog 类重写了父类的 makeSound() 方法。
在主程序中,我们创建了一个 Animal 对象和一个 Dog 对象,并分别调用它们的 makeSound() 方法。由于方法的选择是在运行时确定的,因此当我们将 Dog 实例向上转型为 Animal 类型并调用 makeSound() 方法时,实际上调用的是 Dog 类的实现,输出 The dog barks。
需要注意的是,多态只适用于实例方法,而不适用于静态方法或属性。此外,final 方法也不能被重写,因此也不会发生多态。
当我们谈论多态时,可以用一个简单的比喻来解释。假设有一家动物园,里面有各种各样的动物,包括狗、猫、鸟等等。
在这个动物园中,每个动物都可以发出声音。但是不同的动物发出的声音是不一样的,比如狗会叫汪汪,猫会叫喵喵。
现在我们站在动物园门口,看到一个动物走过来。我们并不知道它是什么动物,只是知道它可以发出声音。于是我们问它:“你能发出声音吗?”这时候,无论这个动物是狗、猫还是其他动物,它都会回答:“我会发出声音。”
这里的关键是,我们对这个动物的了解只限于它能发出声音这个特征,而不关心它究竟是什么动物。这就是多态的一种体现。我们无需关心对象的具体类型,只需要知道它们具备某个共同的特征或行为,然后以统一的方式与它们进行交互。
在这个比喻中,动物园中的动物就像是不同类的对象,它们都实现了一个共同的接口或继承了一个共同的父类。这个共同的接口或父类规定了它们要实现的方法,比如发出声音。而我们站在门口询问动物是否能发出声音,就像是调用这个共同的方法。
通过多态,我们可以以一种统一的方式处理不同类型的对象,而无需关心它们的具体类型。这使得代码更加灵活和可扩展,也方便了代码的维护和管理。
在 Java 中,构造器是一种特殊类型的方法,它用于创建和初始化对象。构造器的名称必须与类的名称完全相同,它没有返回类型(包括 void),并且通常具有公共访问修饰符,以便其他类可以使用它来创建该类的对象。
以下是几个示例类,其中每个类包含一个构造器:
示例1:
public class Person {
private String name;
private int age;
// 构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 方法
public void sayHello() {
System.out.println("Hello, my name is " + name + ", and I am " + age + " years old.");
}
}
我们定义了一个名为 Person 的类,它具有两个私有字段 name 和 age,以及一个公共构造器。构造器的参数与字段名称匹配,并且我们使用 this 关键字来引用类的字段。
当我们使用 new 操作符创建 Person 对象时,将调用构造器来初始化对象。例如:
Person p = new Person("Bob", 30);
p.sayHello(); // 输出:Hello, my name is Bob, and I am 30 years old.
我们首先使用 new 操作符创建一个 Person 对象,并传递 “Bob” 和 30 作为参数。这将调用 Person 类的构造器,并将参数值分配给 name 和 age 字段。
然后,我们调用 sayHello() 方法,它将输出一个字符串,其中包含创建的 Person 对象的名称和年龄信息。
需要注意的是,如果我们没有显式定义任何构造器,则 Java 编译器将生成一个默认构造器。默认构造器没有参数,并且不执行任何操作(除了隐式地调用超类的默认构造器,如果有的话)。
示例2: 无参构造
Day11606.java
package com.determination;
public class Day11606 {
public static void main(String[] args) {
Dog dog=new Dog(); //无参构造
dog.name="大黄";
dog.age=2;
dog.shot();
}
}
Dog.java
package com.determination;
public class Dog {
public String name;
public int age;
public void shot()
{
System.out.println(name+"叫了一声!!");
}
}
示例3: 有参无参构造均有
Day11605.java
package com.determination;
public class Day11605 {
//一个项目只存在一个main方法
public static void main(String[] args) {
//new 实例化一个对象
Person person=new Person("wind");
System.out.println("这是个人(类),这个人是谁(对象)"+person.name);
}
}
Person.java
package com.determination;
import java.security.PublicKey;
public class Person {
//一个类即使什么都不写,也会存在一个方法
//显示的定义构造器
String name;
//1.使用new关键字,本质就是调用构造器
//2.用构造器来初始化
public Person()
{
}
//有参构造,一旦定义了有参构造,无参就要显示定义
public Person(String name)
{
this.name=name;
}
}
总的来说
1.构造器方法名和类名一致
2. 没有返回值
作用:
1.new本质是调用构造方法
2. 初始化对象的指值
注意:
1.定义有参构造之后,如果想要使用无参构造,我们必须显示定义一个有参构造。