面向对象的定义
- 面向过程的思想:
- 步骤清晰简单,第一步做什么,第二步做什么...
- 面向过程适合处理一些较为简单的问题
- 面向对象思想:
- 物理类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思考。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
- 对于描述复杂的事物,为了从宏观上把控,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观的操作,仍然需要面向过程的思路去处理。
- 面向对象编程(OOP)本质是:以类的方式组织代码,以对象的组织(封装)数据。
- 面向对象三大特性:
- 封装
- 继承
- 多态
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物;类,是对对象的抽象。
- 从代码运行角度来说是先有类后有对象,类是对象的模板。
类和对象
-
类和对象的关系举例来说就是狗是一个类,而旺财是对象,即类是一种抽象的数据类型,而对象是具体概念的具体实例。
-
创建对象:
-
使用 new 关键字创建对象
-
使用 new 关键字创建的时候,除了分配内存空间之外,还会给创建好的对象,进行默认的初始化以及对类中构造器的调用。
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写 void
public class Application{ public static void main(String[] args){ Student student1 = new Student(); Student student2 = new Student(); student1.name = "xiaoming"; student2.age = 12; } } //创建类 public class Student { //属性:字段 String name; int age; //方法 public void study(){ System.out.println(this.name+"在学习"); } }
-
构造器
- 一个类即使什么都不写,只要创建类就也会存在一个构造方法。
- 使用 new 关键字,本质上是在调用构造器。
- 一旦定义了有参构造,无参构造就必须定义。
- 构造器用来初始化值。
封装
-
优点:
- 封装可以提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统计接口
- 增加系统的可维护性
-
属性私有,get/set
public class Test{ public static void main(String[] args){ Student s1 = new Student(); s1.setName("小明"); System.oout.println(s1.getName()); } } public class Student{ //属性私有 private String name; private int id; private char sex; //get 获取这个数据 public String getName(){ return this.name; } //set 给这个数据设置值 public void setName(String name){ this.name = name; } }
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
-
extends意思为“扩展”。子类是父类的扩展。
-
Java 中只有单继承,没有多继承。
-
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字 extends 来表示
-
子类继承了父类就可以使用父类的全部方法。
public class Test{ public static void main(String[] args){ Student s1 = new Student(); s1.say(); } } //构造父类 public class Person{ public void say(){ System.out.println("说了一句话"); } } //构造子类 public class Student extends Person{ }
-
super:用于子类使用父类的方法
public class Test{ public static void main(String[] args){ Student s1 = new Student(); s1.test("xiaoxiaoming"); //之后会分别输出 xiaoxiaoming xiaoming ming } } //构造父类 public class Person{ protected String name = "ming"; } //构造子类 public class Student extends Person{ privated String name = "xiaoming" public void test(String name){ System.out.println(name); //打印输入的 name 参数 System.out.println(this.name); //打印子类的 name 参数 System.out.prinyln(super.name); //打印父类的 name 参数 } }
- super 必须只能出现在子类的方法或者构造方法中
- super 和 this 不能同时调用方法。
- super 代表父类对象的应用,只能在继承条件下使用;this 代表本身调用者这个对象,没有继承条件也可以使用。
-
方法重写
-
重写是方法的重写,与属性无关。
-
重写需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小 public>Protected>Default>private
- 抛出的异常:范围,可以被缩小,但不能扩大: ClassNotFoundException
-
静态:
public class Test { public static void main(String[] args){ A a = new A(); //方法的调用只和左边,定义的数据类型有关 a.test(); //输出为A=>test() B b = new A(); //父类的引用指向了子类 b.test(); //输出为B=>test() } } public class A extends B{ public static void test(){ System.out.println("A=>test()"); } } public class B{ public static void test(){ System.out.println("B=>test()"); } }
-
非静态:
public class Test { public static void main(String[] args){ A a = new A(); //方法的调用只和左边,定义的数据类型有关 a.test(); //输出为A=>test() B b = new A(); //子类重写了父类的方法 b.test(); //此时输出为A=>test() } } public class A extends B{ //Override 重写 @Override //注解:有功能的注释 public void test(){ System.out.println("A=>test()"); } } public class B{ public void test(){ System.out.println("B=>test()"); } }
-
静态和非静态差别较大,注意两者的区别
-
多态
public class Test{
public static void main(String[] args){
//一个对象的类型是确定的
//new Student();
//new Person();
//但是可以只想的引用类型就不确定了:父类的引用可以指向子类
Student s1 = new Student();
Person s2 = new Student();
}
}
//构造父类
public class Person{
}
//构造子类
public class Student extends Person{
}
-
instanceof (类型转换):用来测试一个对象是否为一个类的实例或者子类实例,语法为:
boolean result = obj instanceof Class // obj是一个对象,Class 表示一个类或者接口。obj 是 Class 类的实例或和子类实例时,结果 result 返回 true,否则返回 false
public class Test{ public static void main(String[] args){ Person p1 = new Person(); Person p2 = new Student(); Student s1 = new Student(); System.out.println(p1 instanceof Student); //false 因为p1 是 Person 类,而 Person 不是 Student 的子类 System.out.println(p2 instanceof Student); //true 因为p2 实际为Student 类 System.out.println(s1 instanceof Student); //true 因为 s1 是 Student 的实例 } } //构造父类 public class Person{ } //构造子类 public class Student extends Person{ }
static的使用
-
静态变量和非静态变量
public class Test{ private static int age; //多线程使用 private double source; public static void main(String[] args){ System.out.println(Test.age); System.out.println(Test.source); //报错,因为非静态变量无法直接调用 //非静态变量调用方法 Test t = new Test(); System.out.println(t.source); //先创建对象再引用对象的非静态变量 } }
-
静态方法和非静态方法
public class Test{ private static int age; //多线程使用 private double source; public void run(){ } public static void go(){ } public static void main(String[] args){ run(); //报错,无法直接调用非静态方法 go(); //调用非静态方法 new Test().run(); //需要先引用非静态方法所属的类再引入非静态方法 } }
-
代码块和静态代码块
public class Test{ { //代码块(匿名代码块) } static{ //静态代码块,最先执行且执行一次 } }
public class Test{ { System.out.println("匿名代码块"); } static{ System.out.println("静态代码块"); } public Test(){ System.out.println("构造方法"); } public static void main(String[] args){ Test test = new Test(); Test test2 = new Test(); } } //输出结果依次为:静态代码块 匿名代码块 构造方法 //第二次输出结果依次为:匿名代码块 构造方法
抽象类
-
abstract 修饰符可以用来修饰方法也可以用来修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类:不能使用 new 关键词来创建对象,它是用来让子类继承的。
- 抽象方法:只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
-
抽象类:
/* 文件名 : Employee.java */ public abstract class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public double computePay() { System.out.println("Inside Employee computePay"); return 0.0; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } }
-
继承抽象类:
/* 文件名 : Salary.java */ public class Salary extends Employee { private double salary; //Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } }
-
实例化子类:
/* 文件名 : AbstractDemo.java */ public class AbstractDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } }
-
-
抽象方法只包含一个方法名,而没有方法体。抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
-
抽象方法:
public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); //其余代码 }
-
继承子类:
/* 文件名 : Salary.java */ public class Salary extends Employee { private double salary; // Annual salary public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } //其余代码 }
-
接口
-
种类:
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范,自己无法写方法,类似于现实世界的“如果你是 xxx,则必须 xxx”
-
声明类的是 class,而声明接口的是 interface
-
举例:
-
建立接口:
public interface UserService{ //接口中如果有也只会有常量不会有变量 public static final int AGE = 99; //接口中所有定义的方法都是抽象的 void add(String name); void delete(String name); void update(String name); void query(String name); }
-
建立实现子类:
//类可以通过 implements 关键字来实现接口 public class User serviceImpl implements UserService { //实现接口的类,必须要重写接口中的方法 @Override public void add (String name){ } @Override public void detele (String name){ } @Override public void update (String name){ } @Override public void query (String name){ } }
-
内部类
-
指写在类里面的类
public class Outer{ private void out(){ System.out.println("这是外部类的方法"); } class Inner{ public void in(){ System.out.println("这是内部类的方法"); } } }
public class Test{ public static void main(String[] args){ Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); //引用内部类 inner.in(); } }