Java从零开始 基础(二)面向对象
创建类
- java的建包标准是 域名倒过来,如域名:https://base.com
- 在src下新建一个package,包名为:com.base
- 在该包下新建两个java class,分别为Student,Application
- 类是一个模板,对象是一个具体的实例
目录结构如下:

创建对象
可以看到,在创建java class之后,会自动生成一个public class
Student.java: 类
package com.base;
// 学生类
public class Student {
// 属性
String name;
int age;
// 方法
public void study(){
System.out.println(this.name+"正在学习");
}
}
Application.java: 实例化抽象类
package com.base;
// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
// new Student() 实例化类 是一个动作
// tom 实例化类后的具体实例,是一个对象
Student tom = new Student();
Student jack = new Student();
// 给对象的属性赋值
tom.name = "Tom";
tom.age = 18;
jack.name = "Jack";
jack.age = 19;
// 调用对象的方法
tom.study();
jack.study();
}
}
构造器
概念
类似python的 __init__方法
一个类即使什么都没写,实际在编译成class文件后,也会生成一个 构造方法。如:
空类Student的class文件:
/.../
package com.base;
public class Student {
public Student(){
}
}
作用
显式定义构造方法
package com.base;
public class Student {
String name;
// 无参构造
// 实例化初始值
/*
public Student(){
this.name = "Tom";
}
*/
// 有参构造,在new Student时,必须传name参数
public Student(String name){
this.name = name;
}
}
实现
改造一下上面的Student类
package com.base;
// 学生类
public class Student {
String name;
int age;
// 构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void study(){
System.out.println(this.name+"正在学习");
}
}
在实例化Student时必须传name和age参数
package com.base;
public class Application {
public static void main(String[] args) {
Student tom = new Student("Tom", 18);
Student jack = new Student("jack", 19);
}
}
三大特性
封装
- 数据的隐藏,仅暴露少量方法给外部调用
- 通过接口来读写对象的数据(读写时可以判断)
- 高内聚,低耦合
- private、get、set
package com.base;
// 学生类
public class Student {
// 属性
public String name; // 共有属性
private int age; // 私有属性
private char sex;
// 提供可操作私有属性的方法
// get 读
public int getAge(){
return this.age;
}
// set 写
public void setAge(int age){
this.age = age;
}
}
package com.base;
public class Application {
public static void main(String[] args) {
Student tom = new Student();
tom.name = "Tom"; // 共有属性可直接调用
tom.setAge(18); // 私有属性不能直接调用
System.out.println(tom.getAge());
}
}
继承
-
java只有单继承,没有多继承
-
子类拥有父类所有的 public、protected 属性/方法
-
所有类都有一个共同的父类 object,预置了一些方法
-
public:完全开放
-
protected 对同胞和子类开放,其他私有
-
default:对同胞开放,其他私有
-
private:完全私有
-
实例化调用子类时,默认先调用父类的构造方法;super()只能出现在子类的方法中
-
调用父类构造方法,必须写在第一行
语法和特点
父类 Person:
package com.base;
// 父类
public class Person {
String name;
int age;
char sex;
public void say() {
System.out.println(name + " 说了一句话");
}
}
子类 Student:
快捷键:ctrl + h 打开继承树
package com.base;
// 子类(派生类)
public class Student extends Person { // 继承语法
}
入口类 Application:
package com.base;
public class Application {
public static void main(String[] args) {
Student tom = new Student();
tom.name= "Tom"; // Student类拥有person的属性和方法
tom.say();
}
}
super关键字
- this:指代自己,类比python的self
- super:指代父类
父类 Person:
package com.base;
// 父类
public class Person {
protected String name = "Tom";
public void eat(){
System.out.println("父类的吃");
}
}
子类 Student:
package com.base;
// 子类(派生类)
public class Student extends Person {
private String name = "Jack";
public void eat(){
System.out.println("子类的吃");
}
public void getName(){
String father_name = super.name; // Tom
String self_name = this.name; // Jack
super.eat(); // 父类的吃
this.eat(); // 子类的吃
}
}
方法重写
- 有继承关系,子类重写父类的方法
- 方法名必须相同、参数列表必须相同
- 子类方法修饰关键字范围不能缩小(如:不能从public 到 protected)
- 子类方法抛出异常范围只能缩小
- 静态方法(static)只能被继承,不能被重写
父类 Person:
package com.base;
public class Person {
public static void test(){
System.out.println("Person");
}
}
子类 Student:
package com.base;
public class Student extends Person {
public static void test(){ // 重写父类test方法
System.out.println("Student");
}
}
入口 Applicaton:
package com.base;
public class Application {
public static void main(String[] args) {
Student s = new Student();
s.test(); // Student
// 父类的引用指向子类
Person p = new Student();
p.test(); // Person,如果去掉父/子类的static,这里就是Student
}
}
多态
- 功能:同一方法因饮用对象的不同而采用多种不同的行为方式(在子类重写父类的方法后,用父类的引用来new子类的对象,调用该方法,执行的是子类的方法)
- 要求:有继承关系,子类重写父类方法
- 使用:父类引用指向子类对象:Person Tom = new Student();
- 错误:父类引用调用子类独有的方法:ClassCaseException异常
- 转换:父类引用可以通过强制转换来调用子类独有的方法
- 注意:多态是方法的多态,属性没有多态
父类 Person:
package com.base;
// 父类
public class Person {
public void test(){
System.out.println("Person");
}
}
子类 Student:
package com.base;
public class Student extends Person {
@Override
public void test() { // 重写父类方法
System.out.println("Student");
}
public void eat(){ // 父类没有的方法
System.out.println("Student");
}
}
入口 Application:
package com.base;
public class Application {
public static void main(String[] args) {
Student s = new Student();
Person p = new Student();
Object o = new Student();
Student stu = new Person(); // 报错 子类引用无法指向父类对象
// 判断两边是否有继承关系,左实例 右类
System.out.println(o instanceof Student);
System.out.println(o instanceof Person);
System.out.println(p instanceof Student);
s.test(); // Student 子类可以调用自己和父类的方法
p.test(); // Student 父类可以调用子类重写的方法,不能调用子类独有的方法
o.test(); // 报错 父类调用子类独有的方法
s.eat(); // student
p.eat(); // 报错
o.eat(); // 报错
((Student) o).test(); // Student 通过强制转换来调用子类独有的方法
((Student) p).eat(); // Student
((Student) o).eat(); // Student
}
}
static 修饰
static修饰的变量/方法,和类一起加载,可以直接调用
package com.base;
// 父类
public class Person {
static int age=10; // 静态变量
int num=5; // 非静态变量
public static void age(){ // 静态方法
System.out.println("age");
}
public void num(){ // 非静态方法
System.out.println("num");
}
public static void main(String[] args) {
int a = age; // 静态变量可以直接使用
age(); // 静态方法可直接调用
int n = num; // 非静态方法不能直接使用,报错
num(); // 报错
Person person = new Person(); // 非静态方法在实例化后调用
int p = person.num;
person.num();
}
}
执行顺序
静态代码块 -> 匿名代码块 -> 构造方法
package com.base;
// 父类
public class Person {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块"); // 只执行一次
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person p = new Person();
}
}
抽象类
- 抽象类:用abstract声明的类;不能new,只能继承,起到约束作用;
- 抽象方法:用abstract声明的方法;抽象方法只能写在抽象类中;只有方法名,没有方法体;非抽象类的子类必须实现父类的抽象方法;
父类(抽象类)Person:
package com.base;
public abstract class Person {
// 抽象方法,只有方法名,没有方法体
public abstract void someThing();
public void eat() {
System.out.println("Eat");
}
}
子类 Student:
package com.base;
public class Student extends Person {
@Override
public void someThing() { // 重写父类的抽象方法(必须重写)
System.out.println("你好");
}
}
接口
- 关键字:interface
- java的类只能单继承,但接口可以多继承
- 接口就是规则,定义好接口之后,让不同的类来实现
- 接口的方法只能是方法,只写方法名,不写方法体
- 只能继承,不能new,没有构造方法;继承之后必须重写接口的方法
接口定义 UserService:
package com.object;
// 使用interface关键字定义接口
// 接口一般都有实现类,实现类以Impl结尾
public interface UserService {
// 接口中所有属性都是常量,默认加上了 public static final
int AGE=99;
// 接口中的所有方法都是抽象的,默认加上了abstract
void addUser(String name);
void delUser(String name);
}
实现类 UserServiceImpl:
package com.object;
// 接口的实现类 关键字:implements
// 继承多个接口用逗号隔开
// 必须重写接口中的方法
public class UserServiceImpl implements UserService, TimeService{
@Override
public void addUser(String name) {
}
@Override
public void delUser(String name) {
}
@Override
public void time() {
}
}
内部类
在类的里面再定义一个类,包括:成员/静态/局部/匿名 内部类
成员内部类
package com.local;
public class OutSide { // 外部类
int a = 10;
// 成员内部类
public class Inner{
public void insideMethod(){
System.out.println(a); // 内部类可直接访问外部类的属性
}
}
}
class run{
public static void main(String[] args) {
OutSide out = new OutSide();
OutSide.Inner inner = out.new Inner();
inner.insideMethod();
}
}
静态内部类
package com.local;
public class OutSide { // 外部类
int a = 10;
// 静态内部类
public static class Inner{
public void insideMethod(){
System.out.println(a); // 报错,加上static后无法访问外部类属性,因为static先实例化,实例化这个内部类的时候,a属性还没实例化
}
}
}
class run{
public static void main(String[] args) {
OutSide out = new OutSide();
OutSide.Inner inner = out.new Inner();
inner.insideMethod();
}
}
局部内部类和匿名内部类
package com.local;
public class OutSide { // 外部类
int a = 10;
public void method(){ // 方法
// 局部内部类
class Inner{
public void insideMethod(){
System.out.println(a);
}
}
new Inner().insideMethod(); // 匿名内部类,直接new完调方法,不用存到变量
}
}
class run{
public static void main(String[] args) {
OutSide out = new OutSide();
out.method();
}
}

浙公网安备 33010602011771号