Java面向对象
面向对象OOP
OOP的本质:以类的方式组织代码,以对象的方式组织(封装)数据
抽象
对象是具体的事物,类是对对象的抽象
先有类后有对象,类是对象的模板
方法
方法的调用
1 //1、静态方法——直接调用 2 public class Student { 3 public static void speak(){ 4 System.out.println("ooooo"); 5 } 6 } 7 public class Demo01 { 8 public static void main(String[] args) { 9 //类名.方法名 即可调用 10 Student.speak(); 11 } 12 } 13 14 //2、非静态方法——需要实例化这个类 15 public class Student { 16 public void speak(){ 17 System.out.println("ooooo"); 18 } 19 } 20 public class Demo01 { 21 public static void main(String[] args) { 22 //实例化这个类Student 23 //对象类型 对象名 = 对象值 24 Student student = new Student(); 25 student.speak(); 26 } 27 }
-
静态方法和类一起加载,非静态方法在类实例化之后才存在,不能在静态方法中调用非静态方法
对象的创建分析
一个项目应该只存在一个main方法,通常在Application类中定义
类是抽象的,需要实例化,实例化后会返回一个自己的对象,通过new关键字可以创建不同的实例
-
new关键字创建对象
使用new创建对象时除了分配内存空间外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
-
构造器(类似C++的构造函数?)
构造器也称为构造方法,必须和类的名字相同,必须没有返回类型(也不能写void)
构造器的作用:①使用new关键字时本质上是在调用构造器;②用于初始化值
一旦定义了有参构造,就必须对无参构造进行显式定义
(idea中alt+insert快捷生成构造器constructor—>直接生成有参/select no生成无参)
1 //定义的学生类 2 public class Student { 3 //属性:字段(静态) 4 String name; 5 int age; 6 //方法(动态) 7 public void study(){ 8 System.out.println(this.name+"studying"); 9 } 10 11 //无参构造器 12 public Student() { 13 } 14 //有参构造器 15 public Student(String name, int age) { 16 this.name = name; 17 this.age = age; 18 } 19 } 20 ==================================================== 21 public class Application { 22 public static void main(String[] args) { 23 24 //实例化默认对象(调用无参构造) 25 Student student01 = new Student(); 26 //实例化对象的同时赋值(调用有参构造) 27 Student student02 = new Student("COLIN",23); 28 System.out.println(student02.name); 29 30 student01.study(); 31 32 } 33 }

-
new对象
-
相当于只是创建了一个引用变量,包含的值和方法存储在堆中,模板存储在方法区(方法区也属于堆)
-
栈存放引用,堆存放具体对象
-
静态方法区static和类一起加载,可以被所有的对象调用
面向对象的三大特性(难点)
三大特性:封装、继承、多态
(修饰符
-
public:类成员能被所有的类直接访问
-
protected:
-
父类的protected方法/属性在同一个包内可见,且子类可见;
-
若子类与父类不在同一包中:
那么在子类中,子类实例可以访问其从父类继承而来的protected方法,而不能访问父类实例本身的protected方法/属性。(自己的理解:父子不同包时,不能通过父类实例化后的对象来访问父类的protected方法/属性,相当于不能直接访问父类的protected对象,必须通过继承)
-
-
Default(无修饰符):类成员只能被同一个包中的类访问
-
private:类成员只能在修饰它的类中被访问,不可以被外部类访问,对外提供get/set方法(封装思想)
封装
“高内聚,低耦合”
-
属性私有
-
通过get/set访问和修改
1 public class Student { 2 //属性私有 3 private String name; 4 private int id; 5 private int age; 6 7 //提供一些可以操作这些属性的方法 8 //即pubilc的get、set方法 9 //get 10 public String getName(){ 11 return this.name; 12 } 13 //set 14 public void setName(String name){ 15 this.name = name; 16 } 17 //可以通过内部的封装让程序更安全 18 //alt+insert 自动生成getter/setter 19 } 20 21 public class Application { 22 public static void main(String[] args) { 23 24 Student student = new Student(); 25 student.setName("colin"); 26 System.out.println(student.getName()); 27 } 28 }
-
封装的好处
-
提高程序安全性,保护数据
-
隐藏代码的实现细节
-
统一接口
-
增加系统的可维护性
-
继承
继承的本质是对某一批类的抽象,是类之间的一种关系(类之间还有依赖、组合、聚合等关系)
子类继承父类:
-
使用关键字extends + 继承的类来表示继承
-
子类拥有父类的全部public属性和方法(私有private不能继承,protected在不同包时必须通过继承实例化才能访问)
-
Java中所有的类都默认继承object类
子类只能有一个父类
final修饰的类不能被继承
1 //Ctrl+H打开继承树 2 //默认、this、super 3 public class Father { 4 protected String name = "xxx"; 5 6 public void print(){ 7 System.out.println("Father"); 8 } 9 } 10 ============================================== 11 //通过extends继承 12 public class Son extends Father{ 13 14 private String name = "yyy"; 15 16 public void test(String name){ 17 //默认调用本方法属性 18 System.out.println(name); //zzz 19 //this调用本类属性 20 System.out.println(this.name); //yyy 21 //通过super调用父类的属性 22 System.out.println(super.name); //xxx 23 } 24 25 public void print(){ 26 System.out.println("Student"); 27 } 28 29 public void test1(){ 30 //默认调用本类方法 31 print(); //Student 32 //this调用本类方法 33 this.print(); //Student 34 //super调用父类方法 35 super.print(); //Father 36 } 37 } 38 =============================================== 39 public class Application { 40 public static void main(String[] args) { 41 Son son = new Son(); 42 son.test("zzz"); 43 son.test1(); 44 } 45 }
子类会默认调用父类的无参构造,调用父类的构造器,必须要在子类的第一行
-
super调用父类方法的注意点:
-
super调用父类的构造方法,必须在构造方法的第一个
-
super只能出现在子类的方法或构造方法中
-
super和this 不能同时调用构造方法
-
-
super和this的区别:
this super 代表的对象 调用对象本身 调用对象的父类 前提 没有继承也可以使用 只能在继承条件下使用 构造方法 本类的构造 父类的构造
(方法重写
重写需要有继承关系,只适用于非静态,子类可以重写父类的方法
-
方法名必须相同,方法体可以不同
-
参数列表必须相同
-
修饰符范围可以扩大不能缩小:public>protected>Defalt>private
-
抛出的异常范围可以被缩小,但不能扩大
为什么需要重写:
-
父类的功能子类不需要,或不满足
idea快捷键:在子类中使用Alt + Insert—>overwrite
多态(还没有完全理解!)
多态:同一个方法根据发送对象不同而采取不同的行为方式
-
父类的引用指向子类的对象
-
对象可以执行的方法取决于对象名左边的对象类型(即对象的引用类型)
Person student = new Student(); (对象类型 对象名 = 对象值);
父类的引用可以指向子类,但父类不能调用子类的方法,对象可执行的方法取决于对象左边的类型
1 public class Person { //父类 2 public void run(){ 3 } 4 } 5 public class Student extends Person{ //子类 6 public void run(){ 7 } 8 public void eat(){ 9 } 10 } 11 12 public class Application { 13 public static void main(String[] args) { 14 //可以指向的引用类型不确定,父类的引用可以指向子类 15 //对象可执行的方法取决于对象左边的类型 16 Student s1 = new Student(); 17 //父类的引用可以指向子类对象,但父类不能调用子类的方法 18 Person s2 = new Student(); 19 Object s3 = new Student(); 20 //多态实例: 21 s1.run(); 22 s2.run();//这里子类重写了父类的方法,执行子类的方法 23 s1.eat(); 24 s2.eat();//Person中没有eat方法,所以不能执行 25 //需要进行强制类型转换:((Student) s2).eat(); 26 } 27 }
多态的注意事项:
-
多态是方法的多态,属性没有多态
-
父类和子类必须有联系才能转换(类型转换异常ClassCastException)
-
多态存在的条件:继承关系,方法重写,父类引用指向子类对象
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类、有关系的类)
多态的意义:??
(instanceof
X instanceof Y 判断两者类型是否有父子关系,如果不在同一分支上(没有父子关系或间接父子关系)会报错
X和Y有父子关系且X实际指向的类型是Y的子类型则返回true,否则返回false
1 public class Application { 2 public static void main(String[] args) { 3 4 //Object > String 5 //Object > Person > Teacher 6 //Object > Person > Student 7 8 Object object = new Student(); 9 //object实际指向的类型为Student 10 System.out.println(object instanceof Student); //true 11 System.out.println(object instanceof Person); //true 12 System.out.println(object instanceof Object); //true 13 System.out.println(object instanceof Teacher); //false 14 System.out.println(object instanceof String); //false 15 16 Person person = new Student(); 17 System.out.println(person instanceof Student); //true 18 System.out.println(person instanceof Person); //true 19 System.out.println(person instanceof Object); //true 20 System.out.println(person instanceof Teacher); //false 21 System.out.println(person instanceof String); //编译报错 22 23 Student student = new Student(); 24 System.out.println(student instanceof Student); //true 25 System.out.println(student instanceof Person); //true 26 System.out.println(student instanceof Object); //true 27 System.out.println(student instanceof Teacher); //编译报错 28 System.out.println(student instanceof String); //编译报错 29 } 30 }
(类型转换
子类转换为父类,向上转型,自动转换,可能丢失自己本来的一些方法
父类转换为子类,向下转型,强制转换
意义:减少重复代码
(static关键字
-
静态/非静态变量
-
静态变量可以通过 类名.变量名 访问,整个包中同名静态变量只有一个,被共享,任意位置可以修改
-
1 public class Father { 2 public static int age = 100; 3 } 4 ==================================== 5 public class Application { 6 public static void main(String[] args) { 7 System.out.println(Father.age); //输出100 8 } 9 }
-
静态/非静态方法
-
静态方法可以直接通过类名调用
-
非静态方法可以直接访问类中静态的方法
-
未加载类之前不能使用非静态的方法
-
-
匿名代码块/静态代码块
1 public class Person { 2 //2 用于赋初值 3 { 4 System.out.println("匿名代码块"); 5 } 6 //1 最先执行,且只执行一次 7 { 8 System.out.println("静态代码块"); 9 } 10 //3 执行构造方法 11 public Person(){ 12 System.out.println("构造方法"); 13 } 14 15 public static void main(String[] args) { 16 Person person = new Person(); 17 } 18 }
-
静态导入包
1 import static java.lang.Math.random; 2 3 public class Person { 4 public static void main(String[] args) { 5 System.out.println(random()); 6 //静态导入不需要Math. + random()就可以执行 7 } 8 }
抽象类和接口
抽象类
1 //抽象类 2 //extends是单继承的 (接口可以多继承) 3 public abstract class Action { 4 //抽象方法,只有方法名,没有方法的实现 5 public abstract void dosomething(); 6 } 7 //继承了抽象类的子类,必须要重写方法,除非子类也是抽象类 8 public class A extends Action{ 9 @Override 10 public void dosomething() { 11 } 12 }
-
抽象类的注意事项:
-
不能(实例化)new抽象类,只能通过子类去实现
-
抽象类中可以写普通方法,抽象方法必须写在抽象类中
-
抽象类构造器:抽象类中可以有构造器,因为抽象类中可以有普通变量,而接口不能有构造器
-
抽象类存在的意义:约束、提高开发效率
-
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有
-
接口:只有规范(抽象方法)
接口就是规范,定义的是一组规则,约束和实现分离:面向接口编程
接口的本质是契约、约束
-
接口是一种约束,只能定义方法名
-
子类实现接口,必须重写其中的方法
-
只有一个方法的接口叫做函数式接口
1 //定义接口的关键字:interface 2 public interface UserService { 3 //接口中的所有定义的方法其实都是抽象的,方法默认是public abstract 4 //接口中定义的属性默认都是常量 public static final (通常不在接口中定义常量) 5 int age = 99; 6 void run(); 7 } 8 public interface TimeService { 9 void timer(); 10 } 11 ========================================================================= 12 //接口的实现类一般使用Impl作结尾 13 //类实现接口:implements + 接口 14 //实现了接口的类必须要重写接口中的方法 15 //利用接口就可以实现多继承! 16 public class UserServiceImpl implements UserService,TimeService{ 17 @Override 18 public void run() { 19 } 20 @Override 21 public void timer() { 22 } 23 24 public static void main(String[] args) { 25 System.out.println(UserService.age); 26 } 27 }
-
接口的作用
-
约束
-
定义了一些方法,让不同的人实现
-
接口中定义的方法默认都是抽象的,属性默认都是常量
-
接口不能被实例化(因为接口中没有构造方法)
-
implements可以实现多个接口
-
必须要重写接口中的方法
-
内部类
内部类:在一个类的内部再定义一个类,分为:①成员内部类 ②静态内部类 ③局部内部类 ④匿名内部类
1 public class Outer { 2 3 private int id = 101; 4 public void out(){ 5 System.out.println("这是外部类的方法"); 6 //局部内部类:方法中的内部类 7 class B{} 8 } 9 10 //内部类可以操作外部类的私有属性/方法 11 //但静态的内部类不能访问外部类(静态先实例化) 12 13 //成员内部类: 14 public class Inner{ 15 //静态内部类: 16 //public static class Inner{ 17 public void in(){ 18 System.out.println("这是内部类的方法"); 19 } 20 public void getID(){ 21 System.out.println(id); 22 } 23 } 24 } 25 26 //一个java类中可以有多个class类,但只能有一个public class类 27 class A{ 28 } 29 ======================================================= 30 public class Application { 31 public static void main(String[] args) { 32 33 Outer outer = new Outer(); 34 //通过外部类来实例化内部类 35 Outer.Inner inner = outer.new Inner(); 36 inner.getID(); 37 38 //匿名内部类:不用将实例保存到变量中 39 new Outer().out(); 40 41 } 42 }

浙公网安备 33010602011771号