寒假学Java-面向对象篇
类声明
package com.LE0.test;
public class Bicycle {
public int cadence; //声明成员变量
public int gear;
public int speed;
// 构造函数(含参)
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// 四个方法
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
通常情况下,类声明可以包含以下组件,按顺序排列:
- 如
public、private等修饰符。 - 类名,按惯例首字母大写。
- 类父类(超类)的名称,如果有的话,并以
extends关键字开头。一个类只能继承(作为子类)一个父类。 - 类实现的接口的逗号分隔列表,如果有的话,并以
implements关键字开头。一个类可以实现多个接口。
public修饰符——字段可被所有类访问。
private修饰符——字段仅可在其自身类中访问。
子类声明/继承
通过extend关键字来继承父类,可以使子类具有父类的属性和方法。
public class MountainBike extends Bicycle {
public int seatHeight;
public MountainBike(int startHeight, int startCadence,
int startSpeed, int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
public void setHeight(int newValue) {
seatHeight = newValue;
}
}
重载
相同名称的方法,但是传递不同的参数列表
public class DataArtist {
...
public void draw(String s) {
...
}
public void draw(int i) {
...
}
public void draw(double f) {
...
}
public void draw(int i, double f) {
...
}
}
可变数量的参数
它是一种手动创建数组的快捷方式,在方法内部, corners 被当作一个数组处理。
public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x)
* (corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y)
* (corners[1].y - corners[0].y);
lengthOfSide1 = Math.sqrt(squareOfSide1);
// more method body code follows that creates and returns a
// polygon connecting the Points
}
传递原始数据类型参数
Java 的方法参数传递规则只有一种值传递。
基本类型参数,如 int 或 double ,是通过值传递给方法的。这意味着对参数值的任何修改仅在该方法的作用域内有效。当方法返回时,参数将消失,对它们的任何修改都会丢失。
public class PassPrimitiveByValue {
public static void main(String[] args) {
int x = 3;
// invoke passMethod() with
// x as argument
passMethod(x);
// print x to see if its
// value has changed
IO.println("After invoking passMethod, x = " + x);
}
// change parameter in passMethod()
public static void passMethod(int p) {
p = 10;
}
}
// 最终结果是 x=3
实例化一个类(创建一个对象)
new 运算符通过分配内存给新对象并返回对该内存的引用来实例化一个类。 new 运算符也会调用对象构造函数。
this关键字
在一个实例方法或构造函数中,这是一个对当前对象的引用——即被调用方法或构造函数的对象。你可以通过使用 this 来引用当前对象中的任何成员。
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {//不使用this关键字
x = a;
y = b;
}
}
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {//使用this关键字
this.x = x;
this.y = y;
}
}
控制类的成员访问权限
访问级别修饰符决定其他类是否可以使用特定字段或调用特定方法。访问控制有两个级别:
- 在顶层—
public,或包私有(无显式修饰符)。 - 在成员级别—
public,private,protected,或包私有(无显式修饰符)。
一个类可以用 public 修饰符声明,在这种情况下,该类对所有的类都可见。如果一个类没有修饰符(默认情况,也称为包私有),它只在自己的包内可见。
下表显示了每个修饰符允许的成员访问权限。
| Modifier 修饰符 | Class 类 | Package 包 | Subclass 子类 | World 世界 |
|---|---|---|---|---|
public |
Y | Y | Y | Y |
protected |
Y | Y | Y | N |
| no modifier 无修饰符 | Y | Y | N | N |
private |
Y | N | N | N |
第一列数据表示类本身是否可以访问由访问级别定义的成员。
第二列表示同一包中的类(无论其父类是什么)是否可以访问该成员。
第三列表示包外声明的该类的子类是否可以访问该成员。
第四列表示所有类是否可以访问该成员。
static关键字
有时,你希望有一些变量是所有对象共有的。这可以通过 static 修饰符来实现。在声明中带有 static 修饰符的字段被称为 static 字段或类变量。它们与类相关联,而不是与任何对象相关联。
class Student {
// 1. 实例变量(无static):每个学生独有,属于对象
String name; // 姓名
int score; // 成绩
// 2. 静态变量(有static):所有学生共有,属于类,只存一份
static String school = "北京大学"; // 学校名称
// 构造方法
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public void showInfo() {
System.out.println("姓名:" + name + ",分数:" + score + ",学校:" + school);
}
}
public class TestStatic {
public static void main(String[] args) {
Student s1 = new Student("张三", 90);
Student s2 = new Student("李四", 85);
s1.showInfo(); // 输出:姓名:张三,分数:90,学校:北京大学
s2.showInfo(); // 输出:姓名:李四,分数:85,学校:北京大学
// 重点:修改静态变量,所有对象都受影响!
Student.school = "清华大学"; // 推荐:类名.静态变量 调用
s1.showInfo(); // 输出:姓名:张三,分数:90,学校:清华大学
s2.showInfo(); // 输出:姓名:李四,分数:85,学校:清华大学
// 静态变量也可以用对象调用(语法允许,但不推荐,可读性差)
s1.school = "复旦大学";
s2.showInfo(); // 输出:姓名:李四,分数:85,学校:复旦大学
}
}
常量
static 修饰符与 final 修饰符结合使用,也可以用来定义常量。 final 修饰符表示该字段的值不能改变。
static final double PI = 3.141592653589793;
嵌套类
Java 允许你在另一个类中定义一个类。
public class OuterClass {
String outerField = "Outer field";
static String staticOuterField = "Static outer field";
class InnerClass {
void accessMembers() {
IO.println(outerField);
IO.println(staticOuterField);
}
}
static class StaticNestedClass {
void accessMembers(OuterClass outer) {
// Compiler error: Cannot make a static reference to the non-static
// field outerField
// IO.println(outerField);
IO.println(outer.outerField);
IO.println(staticOuterField);
}
}
public static void main(String[] args) {
IO.println("Inner class:");
IO.println("------------");
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
innerObject.accessMembers();
IO.println("\nStatic nested class:");
IO.println("--------------------");
StaticNestedClass staticNestedObject = new StaticNestedClass();
staticNestedObject.accessMembers(outerObject);
IO.println("\nTop-level class:");
IO.println("--------------------");
TopLevelClass topLevelObject = new TopLevelClass();
topLevelObject.accessMembers(outerObject);
}
}
public class TopLevelClass {
void accessMembers(OuterClass outer) {
// Compiler error: Cannot make a static reference to the non-static
// field OuterClass.outerField
// IO.println(OuterClass.outerField);
IO.println(outer.outerField);
IO.println(OuterClass.staticOuterField);
}
}
封装
需要让用户知道的才暴露出来,不需要让用户知道的全部隐藏起来。
package com.LE0.test;
public class Person {
private String name;//private防止用户直接通过.name来修改名字绕过封装,简单来说就是必须用我设置的方法来设置name,这里就体现了封装
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String a) { //检测非法数据
if(a.length() > 10){
System.out.println("Name too long");
}
else{
this.name = a;
}
}
public String getName() {
return name;
}
}
package com.LE0.test;
public class Main {
static void main() {
Person p1 = new Person("LE0",20);
p1.setName("lelelelelelelele");
System.out.println(p1.getName());
}
}
总结:private私有化成员变量 → 写getXxx()读属性 → 写setXxx()改属性 + 加校验;
接口
可以类比成生活中的合同或者规范。
package Interface;
public interface Transformer {//实现了一个变形金刚的接口(制定了规则)
void becomeRobot();
void becomeVehicle();
}
package Interface;
public class Bumblebee implements Transformer{ //在Transformer的基础上定义Bumblebee
@Override //重写方法
public void becomeRobot() {
System.out.println("Bumblebee has transformed into a robot.");
}
@Override
public void becomeVehicle() {
System.out.println("Bumblebee has transformed into a vehicle.");
}
}
package Interface;
public class Main {
static void main() {
Bumblebee bumblebee = new Bumblebee();
bumblebee.becomeRobot();
bumblebee.becomeVehicle();
}
}
output:
Bumblebee has transformed into a robot.
Bumblebee has transformed into a vehicle.
异常
异常(Exception)是指程序执行过程中发生的非正常事件,可能导致程序的中断或者崩溃。
Exception继承于Throwable这个父类,Throwable还有一个子类Error。
Error是由Jvm自身所导致的错误,如内存溢出。接下来主要讨论的是Exception。
Java中的异常分为两大类
- 检查异常:在编译时必须处理的异常,如
IOException或ClassNotFoundException。 - 非检查异常:不要求在编译时处理的异常,如
NullPointerException。
检查异常很好理解,遇到找不到类名等情况,编译器会标红,必须在编译前修改。
非检查异常就是过了编译,但是在运行时出现了问题,比如说数组越界,分母等于0等情况。
package Exception;
public class main {
static void main() {
String [] arr = new String[10];
for(int i=0; i< 11;i++){
arr[i] = "Hello " + i;
}
}
}
output://数组越界异常
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
at Exception.main.main(main.java:7)
package Exception;
import java.util.Scanner;
public class main {
static void main() {
Scanner scanner = new Scanner(System.in);
int a = 10;
int b = scanner.nextInt();
System.out.println(a / b);
}
}
output://算数异常
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Exception.main.main(main.java:14)
异常处理
try-catch语句(快捷键crtl+alt+t)
package Exception;
import java.util.Scanner;
public class main {
static void main() {
try {
Scanner scanner = new Scanner(System.in);
int a = 10;
int b = scanner.nextInt();
System.out.println(a / b);
} catch (Exception e) {
System.out.println("算式异常");
}
}
}
package Exception;
import java.util.Scanner;
public class main {
static void main() {
try {
String [] arr = new String[10];
for(int i=0; i< 11;i++){
arr[i] = "Hello " + i;
}
Scanner scanner = new Scanner(System.in);
int a = 10;
int b = scanner.nextInt();
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("算式异常");
} catch (ArrayIndexOutOfBoundsException e1){
System.out.println("数组越界异常");
} finally {
System.out.println("程序结束");
}
}
}
output://遇到异常直接抛出,try中后面的代码就不执行了,finally中的代码最后一定执行
数组越界异常
程序结束
自定义异常
package Exception;
public class MyExcetion extends Exception{ //继承Exception
public MyExcetion(String message) {
super(message);
}
}
package Exception;
public class main {
static void main() throws MyExcetion {
try {
String[] arr = new String[10];
for (int i = 0; i < 11; i++) {
arr[i] = "Hello " + i;
}
} catch (Exception e) {
throw new MyExcetion("自定义异常");
}
}
}
output:
Exception in thread "main" Exception.MyExcetion: 自定义异常
at Exception.main.main(main.java:13)

浙公网安备 33010602011771号