面向对象基础 1.class和instance class即类,instance即实例。
class是一种对象模版,它定义了如何创建实例,因此,class本身就是一种数据类型;
而instance是对象实例,instance是根据class创建的实例,可以创建多个instance,每个instance类型相同,但各自属性可能不相同。
2.实例 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 package oop;class City { public String name; public double lattitude; public double longitude; } public class oop1 { public static void main (String[] args) { City frist = new City(); frist.name = "shanghai" ; frist.lattitude = 11 ; frist.longitude = 111 ; System.out.println(frist.name); System.out.println(frist.lattitude); System.out.println(frist.longitude); } }
3. 实例讲解
City类中包含了3个字段(field,有些语言叫做属性),通过class我们实现了数据的封装
public可以用来修饰方法和字段,表示其可以被外部访问
创建实例用new,用Class名作为实例的数据类型
访问实例属性时可以用变量.字段
的形式,但是如果用private修饰了该属性则会报错
方法 1.方法的引入 上一级中,我们直接把属性用public
修饰,把属性暴露给外部可能会破坏封装性。所以我们往往采用private
修饰属性,然后通过方法 来读取属性赋值
2.参数绑定 基本类型参数的传递,是调用方值的复制。双方各自的后续修改,互不影响
3.实例 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 33 34 35 package oop;public class opp2 { public static void main (String[] args) { Person Jhon = new Person(); Jhon.setBirth(2000 ); System.out.println(Jhon.getage()); } } class Person { private String name; private int birth; public void setBirth (int birth) { this .birth = birth; } public int getage () { return calcAge(2020 ); } private int calcAge (int currentYear) { return currentYear - this .birth; } }
4.实例讲解
public int getage()
该语句中,public
用于修饰方法是否供外部调用,int
则是该方法的返回数据类型
通过this.field
就可以访问当前实例的字段,如果命名没有冲突实际上可以省略this
this.birth = birth
前一个birth
指向实例的一个属性,后一个birth
则是外部传入的参数,因为命名重复,所以要用this修饰
构造方法 1.构造方法应用 创建对象实例时,我们可以使用构造方法让内部字段初始化,其相当于类内部一个和类同名的特殊的方法。
2.默认构造方法 如果一个类没有定义构造方法,编译器会为我们生成一个默认的构造方法,因而我们可以在new Person()
调用
如果我们自定义了一个构造方法,那么默认的构造方法将不会被创建
3.实例 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 package oop;public class opp3 { public static void main (String[] args) { Person2 ming = new Person2("小明" , 21 ); System.out.println(ming.getAge()); System.out.println(ming.getName()); } } class Person2 { private String name; private int age; public String getName () { return name; } public int getAge () { return age; } public Person2 (String name,int age) { this .age = age; this .name = name; } }
方法重载 1.方法重载介绍 在一个类中,如果存在一系列的方法功能方法名一样,但是参数不同。这种方法名相同,但各自的参数不同,称为方法重载(Overload)
方法重载参数不同,但是返回值类型通常相同
2.实例 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 package oop;public class opp4 { public static void main (String[] args) { Person4 ming = new Person4(); ming.setName("xiao" , "ming" ); System.out.println(ming.getname()); } } class Person4 { private String name; public String getname () { return name; } public void setname (String name) { this .name = name; } public void setName (String fname, String lname) { this .name = fname + lname; } }
继承 1.继承的应用 通过继承子类可以获得父类的所有功能,还可以在父类基础上编写额外的功能。
类自动获得了父类的所有字段,严禁定义与父类重名的字段
父类又可以称为超类,基类
子类又可以称为扩展类
2.继承树 除了object外,任何类都会继承于某个类,一个子类只能有一个父类,一个父类允许存在多个子类
3.protected与private 如果父类中的属性或方法是private
修饰,子类同样也是无法访问到的,这时我们可以使用protected修饰,可以把属性和方法的权限控制在继承树内部
4.子类的构造方法 子类是无法继承父类的任何构造方法的,编译器会自动为我们添加super()
来调用父类的构造方法,故若是父类存在带参数的构造方法,要手动在子类中调用
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 public class Main { public static void main (String[] args) { Student s = new Student("Xiao Ming" , 12 , 89 ); } } class Person { protected String name; protected int age; public Person (String name, int age) { this .name = name; this .age = age; } } class Student extends Person { protected int score; public Student (String name, int age, int score) { super (name, age); this .score = score; } }
7.向上转型与向下转型 (1)向上转型
1 2 3 4 Student s = new Student(); Person p = new Student();
这种把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting)
注意到继承树是Student > Person > Object
,所以,可以把Student
类型转型为Person
,或者更高层次的Object
1 2 3 4 Student s = new Student(); Person p = s; Object o1 = p; Object o2 = s;
(2)向下转型
如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)
1 2 3 4 5 6 Person p1 = new Student(); Person p2 = new Person(); Student s1 = (Student) p1; Student s2 = (Student) p2;
6.实例 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class Main { public static void main (String[] args) { Person p = new Person("小明" , 12 ); Student s = new Student("小红" , 20 , 99 ); Student ps = new PrimaryStudent("小军" , 9 , 100 , 5 ); System.out.println(ps.getScore()); } } class Person { protected String name; protected int age; public Person (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } } class Student extends Person { protected int score; public Student (String name, int age, int score) { super (name, age); this .score = score; } public int getScore () { return score; } } class PrimaryStudent extends Student { protected int grade; public PrimaryStudent (String name, int age, int score, int grade) { super (name, age, score); this .grade = grade; } }
多态 1.覆写 子类中不能存在与父类重名的属性,但子类可以覆写父类的方法,覆写方法时方法名和返回类型要相同
1 2 3 4 5 6 7 8 9 class Person { public void run () {} } public class Student extends Person { @Override public void run (String s) {} }
2.多态 Java的实例方法调用是基于运行时的实际类型的动态调用(new Student()
),而非变量的声明类型(Person
)
多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法
多态具有一个强大的功能——允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码
3.实例 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 public class Main { public static void main (String[] args) { Income[] incomes = new Income[] { new Income(3000 ), new Salary(7500 ), }; System.out.println(totalTax(incomes)); } public static double totalTax (Income... incomes) { double total = 0 ; for (Income income: incomes) { total = total + income.getTax(); } return total; } } class Income { protected double income; public Income (double income) { this .income = income; } public double getTax () { return income * 0.1 ; } } class Salary extends Income { public Salary (double income) { super (income); } @Override public double getTax () { if (income <= 5000 ) { return 0 ; } return (income - 5000 ) * 0.2 ; } }
4.多态补充 (1)调用父类中被覆写的方法用super
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Person { protected String name; public String hello () { return "Hello, " + name; } } Student extends Person { @Override public String hello () { return super .hello() + "!" ; } }
(2)final修饰可以防止方法被子类覆写如:public final String hello()
抽象类 1.面向抽象编程 抽象类和其中的抽象方法本身是无法执行的,其强制了子类必须实现其定义的抽象方法,即相当于定义了一个规范
这种引用高层类型,避免引用子类型的方式,称为面向抽象编程
有以下优点:
上层代码只定义规范(例如:abstract class Person
);
不需要子类就可以实现业务逻辑(正常编译);
具体的业务逻辑由不同的子类实现,调用者并不关心
2.实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Main { public static void main (String[] args) { Person p = new Student(); p.run(); } } abstract class Person { public abstract void run () ; } class Student extends Person { @Override public void run () { System.out.println("Student.run" ); } }
接口 1.接口介绍 接口(interface)中没有字段,接口中定义的所有方法默认为public abstract
2.接口实现 当用一个具体的class实现一个interface时,需要用到implements关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface Person { void run () ; String getName () ; } class Student implements Person { private String name; public Student (String name) { this .name = name; } @Override public void run () { System.out.println(this .name + " run" ); } @Override public String getName () { return this .name; } }
3.接口继承 接口也可以通过继承扩展
1 2 3 4 5 6 7 8 interface Hello { void hello () ; } interface Person extends Hello { void run () ; String getName () ; }
静态 1.静态字段 class中定义的字段我们称为实例字段,其一般有着独立性,各个实例间互不影响
但是如果我们用static
一个静态修饰一个字段,那么所有的实例都会共享这个字段的空间
对于静态字段,我们无论修改哪个实例,所有实例的静态字段都会改动
我们往往采用类名.静态字段
访问静态对象,如:Person.number = 99;
2.静态方法 静态方法可以通过类名直接调用,不需要一个实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Main { public static void main (String[] args) { Person.setNumber(99 ); System.out.println(Person.number); } } class Person { public static int number; public static void setNumber (int value) { number = value; } }
3.接口的静态字段 因为接口是一个纯抽象类,所以它不能定义实例字段,但是可以有静态字段
1 2 3 4 5 public interface Person { int MALE = 1 ; int FEMALE = 2 ; }
包 位于同一个包的类,可以访问包作用域的字段和方法。不用public
、protected
、private
修饰的字段和方法就是包作用域
可以用import语句导入其他包的class
作用域 可参考:https://www.liaoxuefeng.com/wiki/1252599548343744/12604662156765122