类与对象

类定义一种全新的数据类型,包含一组变量和函数;对象是类这种类型对应的实例。

例如在一间教室中,可以将Student定义成类,表示“学生”这个抽象的概念。那么每个同学就是Student类的一个对象(实例)。

源文件声明规则

  • 一个源文件中只能有一个public类。
  • 一个源文件可以有多个非public类。
  • 源文件的名称应该和public类的类名保持一致。
  • 每个源文件中,先写package语句,再写import语句,最后定义类。

类的定义

  • public: 所有对象均可以访问
  • private: 只有本类内部可以访问
  • protected:同一个包或者子类中可以访问
  • 不添加修饰符:在同一个包中可以访问
  • 静态(带static修饰符)成员变量/函数与普通成员变量/函数的区别:
    • 所有static成员变量/函数在类中只有一份,被所有类的对象共享;
    • 所有普通成员变量/函数在类的每个对象中都有独立的一份;
    • 静态函数中只能调用静态函数/变量;普通函数中既可以调用普通函数/变量,也可以调用静态函数/变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//Point类
package org.ep.point;

public class Point {
private int x;
private int y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

public void setX(int x) {
this.x = x;
}

public void setY(int y) {
this.y = y;
}

public int getX() {
return x;
}

public int getY() {
return y;
}

public String toString() {
return String.format("(%d, %d)", x, y);
}
}
1
2
3
4
5
6
7
8
9
10
11
//Main
package org.ep;

import org.ep.point.Point;

public class Main {
public static void main(String[] args) {
Point point = new Point(3, 4);
System.out.println(point.toString());
}
}

输出

1
(3, 4)

类的继承

每个类只能继承一个类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//ColorPoint子类
package org.ep.point;

public class ColorPoint extends Point {
private String color;

public ColorPoint (int x, int y, String color) {
super(x, y);
this.color = color;
}

public void set_Color(String color) {
this.color = color;
}

public String toString() {
return String.format("(%d, %d, %s", super.getX(), super.getY(), color);
}
}

类的多态

同一个类的实例,调用相同的函数,运行结果不同.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Main
package org.ep;

import org.ep.point.Point;
import org.ep.point.ColorPoint;

public class Main {
public static void main(String[] args) {
Point point1 = new Point(3, 4);
Point point2 = new ColorPoint(3, 4, "red");

System.out.println(point1.toString());
System.out.println(point2.toString());
}
}

输出

1
2
(3, 4)
(3, 4, red)

接口

interfaceclass类似。主要用来定义类中所需包含的函数。

接口也可以继承其他接口,一个类可以实现多个接口。

接口的定义

接口中不添加修饰符时,默认为public

1
2
3
4
5
6
//Role接口
interface Role {
public void greet();
public void move();
public int getSpeed();
}

接口的继承

每个接口可以继承多个接口

1
2
3
4
//Hero子接口
interface Hero extends Role {
public void attack();
}

接口的实现

每个类可以实现多个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package org.ep.role.impl;

import org.ep.role.Hero;
import org.ep.role.Role;

public class Zeus implements Hero, Role {
private final String name = "Zeus"; //final表示常量
public void attack() {
System.out.println(name + ": Attack");
}

public void greet() {
System.out.println(name + ": Hello");
};
public void move() {
System.out.println(name + ": Move");
};
public int getSpeed() {
return 10;
};
}

接口的多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Zeus
package org.ep.role.impl;

import org.ep.role.Hero;
import org.ep.role.Role;

public class Zeus implements Hero {
private final String name = "Zeus"; //final表示常量
public void attack() {
System.out.println(name + ": Attack");
}

public void greet() {
System.out.println(name + ": Hello");
};
public void move() {
System.out.println(name + ": Move");
};
public int getSpeed() {
return 10;
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//Athena
package org.ep.role.impl;

import org.ep.role.Hero;

public class Athena implements Hero {
private final String name = "Athena";
@Override
public void attack() {
System.out.println(name + ": Attack");
}

@Override
public void greet() {
System.out.println(name + ": Hello!!");
}

@Override
public void move() {
System.out.println(name + ": Move");
}

@Override
public int getSpeed() {
return 20;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Main
package org.ep;

import org.ep.role.Hero;
import org.ep.role.impl.Athena;
import org.ep.role.impl.Zeus;

public class Main {
public static void main(String[] args) {
Hero[] heros = {
new Zeus(),
new Athena(),
};

for (Hero hero : heros) {
hero.greet();
}
}
}

输出

1
2
Zeus: Hello
Athena: Hello!!

一个类想要实现一个接口,就必须实现接口里的所有函数

例题

  1. 斐波那契数列

    输入一个整数 n,求斐波那契数列的第n项。

    假定从 0开始,第 0项为 0。

    输入样例

    1
    5

    输出样例

    1
    5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //Solution.java
    package org.ep;

    public class Solution {
    public int Fibonacci(int n) {
    if (n <= 1) return n;
    else return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
    }
  2. 替换空格

    请实现一个函数,把字符串中的每个空格替换成%20

    数据范围

    0≤输入字符串的长度 ≤1000
    注意输出字符串的长度可能大于 1000

    输入样例

    1
    "We are happy."

    输出样例

    1
    "We%20are%20happy.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //Main.java
    package org.ep;

    import java.util.Scanner;

    public class Main {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String strInput = sc.nextLine();
    StringBuffer str = new StringBuffer(strInput);
    Solution solution = new Solution();
    System.out.println(solution.replaceSpaces(str));
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    //Solution.java
    package org.ep;

    class Solution {
    public String replaceSpaces(StringBuffer str) {
    return str.toString().replace(" ", "%20");
    }
    }
  3. 求1+2+…+n

    1+2+…+n,要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 (A?B:C)

    数据范围

    1≤n≤50000

    输入样例

    1
    10

    输出样例

    1
    55

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //Solution.java
    package org.ep;

    class Solution {
    public int getSum(int n) {
    int sum = 0;
    for (int i = 1; i <= n; i ++)
    sum += i;
    return sum;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //Main.java
    package org.ep;

    import java.util.Scanner;

    public class Main {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    Solution solution = new Solution();
    System.out.println(solution.getSum(n));
    }
    }

习题

  1. 左旋转字符串

    字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。

    请定义一个函数实现字符串左旋转操作的功能。

    比如输入字符串”abcdefg”和数字 2,该函数将返回左旋转 2位得到的结果”cdefgab”。

    数据范围

    输入字符串长度 [0,1000]

    输入样例

    1
    2
    abcdefg
    2

    输出样例

    1
    cdefgab

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //Solution.java
    package org.ep;

    class Solution {
    public String leftRotateString(String str,int n) {
    String str1 = str.substring(n, str.length());
    String str2 = str.substring(0, n);
    return str1 + str2;
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    //Main.java
    package org.ep;

    import java.util.Scanner;

    public class Main {
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String str = sc.next();
    int n = sc.nextInt();
    Solution solution = new Solution();
    System.out.println(solution.leftRotateString(str, n));
    }
    }
  2. 把字符串转换成整数

    写一个函数 StrToInt,实现把字符串转换成整数这个功能。

    当然,不能使用 atoi 或者其他类似的库函数。

    函数应满足下列条件:

    • 忽略所有行首空格,找到第一个非空格字符,可以是 ‘+/−’ 表示是正数或者负数,紧随其后找到最长的一串连续数字,将其解析成一个整数;
    • 整数后可能有任意非数字字符,请将其忽略;
    • 如果整数长度为 0,则返回 0;如果整数大于 INT_MAX(231−1),请返回 INT_MAX;如果整数小于INT_MIN(−231) ,请返回 INT_MIN

    数据范围

    输入字符串长度 [0,20]

    输入样例

    1
    "123"

    输出样例

    1
    123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Solution.java
class Solution {
public int strToInt(String str) {
str = str.trim();
if (str.length() == 0) return 0;
int sign = 1;
char first = str.charAt(0);
if (first == '+' || first == '-') {
if (first == '-') sign = -1;
str = str.substring(1);
}

long res = 0;
for (char c : str.toCharArray()) {
if (c < '0' || c > '9') break;
int x = c - '0';
res = res * 10 + x;
if (res > 1e11) break;
}

res *= sign;

if (res > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
else if (res < Integer.MIN_VALUE)
return Integer.MIN_VALUE;
else
return (int)res;
}
}
1
2
//Main.java