class Person {
// 每个成员变量/方法(包括构造方法)都需要指明控制访问权限
private String name = "Unamed"; // 和C++一样,
// 可以在定义时对成员变量规定初始化
// 同样也会被构造方法覆盖掉
// final 变量不可更改,类似于const
// static表示该字段/方法是静态的(属于类而不是对象),与C++类似
public static final String SPECIES = "Homo sapien";
private static int POPULATION = 0;
private int age = 18;
protected String[] nicknames;// 如果没有在构造方法中初始化字段,
// 引用类型默认是null,基本类型用默认值
public Person() {
this("Whoever", 18); // 可以使用类似C++委托构造的语法
}
public Person(String name, int age) {
// 和C++一样,如果我们定义了构造方法
// 那么编译器就不会再生成默认构造方法
POPULATION++;
this.name = name;
this.age = age;
this.nicknames = new String[];
}
public String getName() {
return this.name;
}
// 对于引用参数,传参是引用的
public void setName(String name) {
this.name = name; // this是“引用”,而不是指针,不需要"->"语法
// 赋值却是拷贝的,对于String,默认就是深拷贝
}
public int getAge() {
return this.age;
}
// 对于基本类型(如int),传参是拷贝
public void setAge(int age) { // 没有“默认参数”的语法
if (age < 0 || age > 100) {
throw new IllegalArgumentException("invalid age value");
}
this.age = age;
}
public void setNicknames(String... nicknames) {
// 可变参数的声明和使用比C++简单得多
// 实际上几乎就是一个数组,只不过能够接受null值
// 且不需要手动来(new T[])构造参数,直接(T t1, T t2, ...)就好
this.nicknames = nicknames;
}
public static class PopulationManagement{ // Java支持嵌套类
public static void addPopulation(int n){
Person.POPULATION += n; // 嵌套类拥有访问private的权限
}
}
public void say(){
System.out.println("Hi!\n");
}
public void say(String sth){ // 支持重载
System.out.println(sth);
}
public final void sayAge(){ // final 方法不能覆写
System.out.println(age);
}
@Override
public String toString(){ // 覆写Object的方法
// 还可以覆写equals、hashCode等方法
String res = "name: " + name + ", age: " + age; // 局部变量
return res;
}
}
class Student extends Person { // 继承用extends关键字,Java只支持单继承
// 所有的class最终都继承自Object
// 子类无法访问父类的private字段/方法
// 但可以访问父类(以及祖先类)protected字段/方法
private int score;
public Student(String name, int age, int score){
super(name, age); // 不同于C++,Java子类的构造方法必须手动被调用
// 子类不会继承任何父类的构造方法
this.score = score;
}
@Override // 不是必需的,但可以帮助编译器检查
public say(){
System.out.println(getName()); // 基类private变量不可访问
for(String nickname : super.nicknames){ // 基类protected变量可访问
System.out.println(nickname);
}
}
public int getScore(){...}
public void setScore(int score){...}
}
Person.SPECIES == "Homo sapien"
Person.PopulationManageerson.PopulationManage
P
Person p1 = new Person();
Person p2 = new Student(); // 基类引用可以指向派生类,称为向下转型
Student s1 = (Student) p1; // runtime error! ClassCastException!
Student s2 = (Student) p2; // ok
p2.say(); // 基于运行时多态,会调用Student的say方法
// instanceof 操作符
p1 instance of Person == true
p1 instance of Student == false
p2 instance of Person == true
p2 instance of Student == true
// Java 14 以后
Object obj = "hello";
f (obj instanceof String s) {
// 可以直接使用变量s:
System.out.println(s.toUpperCase());
}
public sealed class Shape permits Rect, Circle, Triangle {
// 用sealed关键字修饰后,该类只允许permits后面Rect, Circle, Triangle三个类继承
// Java17后支持,C++似乎没有类似的语法?
public abstract double area(); // 类似于 C++ virtual f() = 0;
// 同样,含有抽象方法的类是抽象类,不能实例化
}
public final class Rect extends Shape {...} // final修饰的类不允许再被继承
package world.of.transformers // 包类似于namespace,但和Python的包概念更像
// 包之间没有父子关系,包要和项目中的目录结构对应
// 比如,这个包可以访问所有包名为world.of.transformers的文件的内容
// 推荐的做法是使用倒置的域名来确保唯一性,eg. org.apache
/*
package_sample
└─ src
└─ world
└─ of
└─transformers
└─Verhicle.java
*/
interface Verhicle { // 接口相当于没有非静态字段的抽象类
void run();
}
interface Car extends Verhicle{ // 接口也可以继承
default void getFueled(){ // 实现类如果不覆写default方法则使用默认的
System.out.println("fueling\n");
}
void startEngine(){
Runnable r = new Runnable() { // 匿名类,实现Runnable接口
@Override
public void run(){
while(true){
Thread.sleep(10000);
System.out.println("Engine running\n");
}
}
}
}
}
interface Bicycle extends Verhicle{
public static wheelNum = 2; // 接口只可以有静态字段
}
public /*这个public表示其他包可以访问他*/ class Transformer implements Verhicle {
// 类要实现接口,
// 不是用extends,而是用implements
void run() {
System.out.println("Transformer running\n");
}
}
请随意转载