Java基础
类
一个类包含:
- 属性(成员变量),表示类的静态特征
- 方法(成员方法),表示类的动态行为
访问修饰符指定了成员变量的可见性和访问权限。
常用的修饰符包括
-private
(私有,只能在类内部访问)
-public
(公共,可以从任何地方访问)
-protected
(受保护,可以在类内部和子类中访问)
基本写法
public class Person {
// 成员变量的定义:访问修饰符 数据类型 变量名
private String name;
// 构造方法
// 是一种特殊类型的成员方法,在创建对象时自动调用,通常用于为成员变量赋初始值
// 无参构造函数
public Person() { // 在构造函数中进行初始化
age = 20;
name = "zs";
}
// 带参数的构造函数
public Person(String name) {
this.name = name;
}
// 成员方法的定义
// 访问修饰符 返回类型 方法名(参数列表) {
// 方法体
// }
public void sayHello() {
}
// 主方法,程序的入口
public static void main(String[] args) {
// 创造一个 Person 对象
Person person1 = new Person("Tom");
// 调用对象的方法
person1.sayHello();
}
}
抽象类
在建立类时,有的时候会有一些比较抽象的概念,比如形状, 它们创建实例对象并没有什么意思,形状既没有一个特定的type
值,也无法计算具体的面积,这时候,我们就会将其定义为抽象类。
抽象类使用abstract
来声明,并且不能实例化,类中包含一些通用的属性和方法。
abstract class Shape {
}
抽象方法是一种没有具体的方法,只有方法的声明,没有方法体,并且只能存在于抽象类中。也使用abstract
来声明。
// 抽象类 Shape
abstract class Shape {
// 抽象方法: 没有具体的实现,只是定义了方法名称、参数和返回类型,具体的实现由子类提供。
public abstract double calculateArea();
}
面向对象的三大特性
封装
主要目的:保证数据的安全性。通过封装,隐藏对象中一些不希望被外部所访问到的属性或方法,具体分为两步:
- 将对象的属性名,修改访问修饰符为
private
, 这样就只能在内部类中访问,其他类访问不了。 - 提供
getter
和setter
来获取和设置对象的属性
public class Circle {
// 1. 将属性名,设置为私有的
private int radius;
// 构造函数
public Circle(int radius) {
setRadius(radius);
}
// 2. 定义set方法,设置属性(若希望属性只读,可去掉)
// 设置半径,包括数据验证
public void setRadius(int radius) {
if (radius > 0) {
this.radius = radius;
} else {
System.out.println("半径必须为正数");
}
}
// 2. 定义get方法,获取属性(若希望属性不能被外部访问,可去掉)
public int getRadius() {
return radius;
}
}
通过上面的设置,我们可以在外部代码中安全的访问和修改半径的值,这就是封装的思想,将对象的状态隐藏在对象内部,然后提供受控的接口来进行交互。
继承
采用“继承”的方式,使得一个类获取到其他类中的属性和方法。在定义类时,可以在类名后使用extends
指定当前类的父类(超类), 子类可以直接继承父类中的所有属性和方法,从而避免编写重复性的代码,此外我们还可以对子类进行扩展。
继承的格式如下:
class A{
}
class B extends A{
}
类A为父类,extends表示继承,即类 B 继承 类 A, 子类 B 继承父类 A 之后,就获取了父类中声明的所有的属性和方法,并且可以声明自己的属性和方法,实现功能的拓展。
例如
abstract class Shape {
// 定义属性 type
protected String type;
// 定义方法CalculateArea,用来计算图形面积,方法体为空
public double CalculateArea();
// 构造方法
public Shape(String type) {
this.type = type;
}
}
// extends表示继承,即Circle类继承自Shape类
class Circle extends Shape {
private int radius;
public Circle(String type, int radius) {
super(type); // 调用父类的构造方法,传递 type属性
this.radius = radius;
}
// 重写父类的求面积方法
@Override
public double CalculateArea() {
return 3.14 * radius * radius;
}
}
方法的重写:要求子类中的方法(方法名、参数类型和个数、返回类型)必须与父类中的方法相同,然后子类会调用自己的方法而不是父类的同名方法。
多态
指,虽然方法名称相同,但实际调用的方法是根据对象的类型动态确定的。
例:
// 创建 Shape 类型,指向 Circle 对象
Shape myCircle = new Circle(5);
// 虽然是Shape类型,但是调用方法时根据对象本身的类型来处理
double circleArea = myCircle.calculateArea();
System.out.println("圆形的面积:" + circleArea);
// 创建 Shape 类型,指向 Rectangle 对象
Shape myRectangle = new Rectangle(4, 6);
// 虽然是Shape类型,但是调用方法时根据对象本身的类型来处理
double rectangleArea = myRectangle.calculateArea();
System.out.println("长方形的面积:" + rectangleArea);
具有两种形式:
- 编译时多态(静态多态):类有基类和子类,最初,我们可能不知道应该使用哪个类,所以使用基类来调用方法。
- 运行时多态(动态多态):程序运行的时候,会根据对象实际的类来调用相应的方法。
一个Java文件中,只能有一个
public
类,并且文件名必须和该类名匹配。
题目
题目描述
考虑一个简单的图形类层次结构,包括基类 Shape 和两个派生类 Rectangle 和 Circle。每个类都有一个用于计算面积的方法。你的任务是编写一个程序,根据输入数据创建一个图形对象,然后计算并输出其面积。
输入描述
输入包括多行,每行包含一个图形的描述。 描述的第一个单词是图形类型(“rectangle"或"circle”),然后是与该图形相关的参数。 对于矩形,参数是宽度和高度,对于圆形,参数是半径。输入以单词"end"结束。
输出描述
对于每个图形描述,输出其类型和面积。使用两位小数点精度输出面积。
程序编写
import java.util.ArrayList;
import java.util.Scanner;
// 定义抽象类 Shape
abstract class Shape {
protected String type;
public abstract double CalculateArea();
public String GetType() {
return type;
}
}
class Rectangle extends Shape {
private int width;
private int height;
public Rectangle(int width, int height) {
this.type = "Rectangle";
this.width = width;
this.height = height;
}
public double CalculateArea() {
return width * height;
}
}
class Circle extends Shape {
private int radius; // 将半径修改为整数类型
public Circle(int radius) {
this.type = "Circle";
this.radius = radius;
}
public double CalculateArea() {
return 3.14 * radius * radius;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Shape> shapes = new ArrayList<>();
while (true) {
String inputLine = scanner.nextLine();
String[] data = inputLine.split(" ");
String shapeType = data[0];
// 处理不同类型的输入
if (shapeType.equals("end")) {
break;
}
if (shapeType.equals("rectangle")) {
int width = Integer.parseInt(data[1]);
int height = Integer.parseInt(data[2]);
shapes.add(new Rectangle(width, height)); // 添加 Rectangle 对象
} else if (shapeType.equals("circle")) {
int radius = Integer.parseInt(data[1]); // 将半径解析为整数
shapes.add(new Circle(radius)); // 添加 Circle 对象
}
}
// 不同类型调用同一个方法,根据类型的不同处理逻辑也不同
for (Shape shape : shapes) {
System.out.printf("%s area: %.2f%n", shape.GetType(), shape.CalculateArea());
}
}
}