面向对象的方法主要是把事物给对象化,包括其属性和行为。面向对象编程更贴近实际生活的思想。总体来说面向对象的底层还是面向过程,面向过程抽象成类,然后封装,方便使用就是面向对象(万物皆对象)。
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
package com.kuangshen.OOP; public class Student { String name; int age; public void study() { System.out.println(this.name + "在学习" + " 他已经" + this.age + "岁了"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Student student1 = new Student(); Student student2 = new Student(); student1.name = "小明"; student1.age = 12; student2.name = "小红"; student2.age = 11; System.out.println(student1.name + " " + student1.age); } }
类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
其作用如下:
案例如下:
Person.java
package com.kuangshen.OOP; public class Person { //一个类即使什么都不写也会有一个默认构造器方法。与类名相同并且没有返回值 String name; int age; public Person() { this.name= "神州";//可以什么都不写 } public Person(String name) { this.name = name; } public Person(int age, String name) { this.age = age; this.name = name; } }
Application.java
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Person(); System.out.println(person.name); } }
注意:定义有参构造之后,如果想要使用无参构造,我们需要显示的定义一个无参构造(在一般条件下,无参构造不用写,系统也会默认自带一个)。
下面例子会报错,需要把Person.java中的无参构造的注释去掉:
package com.kuangshen.OOP; public class Person { //一个类即使什么都不写也会有一个默认构造器方法。与类名相同并且没有返回值 String name; int age; /*public Person() { this.name= "神州";//可以什么都不写 }*/ public Person(String name) { this.name = name; } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Person(); System.out.println(person.name); } }
该露的露,该藏的藏
封装:数据的隐藏
封装中提出了private关键字,利用这个关键字,可以避免对数据的直接表示,代码如下:
ackage com.kuangshen.OOP; public class Teacher { private int age; private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Teacher teacher = new Teacher(); teacher.setName("天才"); System.out.println(teacher.getName()); // System.out.println(teacher.name);//不可以对数据直接操作 } }
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
继承一般使用extend关键字,其中people.java,people1.java和Application.java的例子如下:
package com.kuangshen.OOP; public class people { private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
package com.kuangshen.OOP; public class people1 extends people{ public void say() { System.out.println(getAge()); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); person.setAge(5); person.say(); } }
继承类型
继承的特性
继承关键字
super关键字
super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
this关键字:指向自己的引用。
后面people.java,people1.java和Application.java的例子如下:
package com.kuangshen.OOP; public class people { protected String name = "天下"; public void print() { System.out.println("1"); } }
package com.kuangshen.OOP; public class people1 extends people{ private String name = "月关"; public void print() { System.out.println("2"); } public void test(String name) { System.out.println(name); System.out.println(this.name); System.out.println(super.name); } public void test1() { print(); this.print(); super.print(); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); person.test("天马"); person.test1(); } }
最终的结果如下:
天马 月关 天下 2 2 1
super构造器
super无参构造器
package com.kuangshen.OOP; public class people1 extends people{ public people1() { //隐藏代码,调用了父类的构造器 super();//可加可不加,但是加了必须在第一行。 System.out.println("使用了子类构造器"); } }
package com.kuangshen.OOP; public class people { public people() { System.out.println("使用了父类构造器"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); } }
super有参构造器
package com.kuangshen.OOP; public class people1 extends people{ public people1() { //影藏代码,调用了父类的构造器 super("人间");//当有参时,如果super不写,那么子类也要变成有参构造,如果写,super要变成有参构造 System.out.println("使用了子类构造器"); } }
package com.kuangshen.OOP; public class people { public people(String a) { System.out.println("使用了父类" + a +"构造器"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { people1 person = new people1(); } }
super注意点
super Vs this
代表的对象不同
前提:
构造方法:
package com.kuangshen.OOP; public class A extends B{ public static void test() { System.out.println("A"); } }
package com.kuangshen.OOP; public class B { public static void test() { System.out.println("B"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); B b = new A();//父类的引用指向了子类 b.test(); } }
输出结果为
A
B
重写的例子(重写只和非静态有关)
package com.kuangshen.OOP; public class A extends B{ //Override重写 @Override//注解:有功能的注释 public void test() { System.out.println("test=>A"); } }
package com.kuangshen.OOP; public class B { public void test() { System.out.println("test=>B"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { //方法的调用只和左边,定义的数据类型有关 A a = new A(); a.test(); B b = new A();//非静态时,子类重写了父类的方法,结果只和子类的结果有关 b.test(); } }
最终的结果为:
A
A
重写的注意点:需要有继承关系,子类继承父类的方法
重写,子类和父类必须要一致,但方法体不同
为什么需要重写:父类的方法,子类不一定需要,或者不一定满足
package com.kuangshen.OOP; public class Student extends Person{ @Override public void run() { System.out.println("Student"); } public void eat() { System.out.println("eat"); } }
package com.kuangshen.OOP; public class Person { public void run() { System.out.println("Person"); } }
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Student s1 = new Student(); Person s2 = new Student(); Object s3 = new Student(); //对象能执行哪些方法,只能看对象左边的类型,和右边关系不大 s1.run(); s2.run(); s1.eat(); ((Student) s2).eat();//父类无法调用子类的方法,只能强制转换成子类 //s2.eat;//会报错 } }
输出结果:
Student
Student
eat
eat
多态注意事项:
以下方法无法重写,自然没有多态
直接看例子:
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Object object = new Student(); System.out.println(object instanceof Student); System.out.println(object instanceof Person); System.out.println(object instanceof Object); System.out.println(object instanceof Teacher); System.out.println(object instanceof String); System.out.println("======================="); Person person = new Student(); System.out.println(person instanceof Student); System.out.println(person instanceof Person); System.out.println(person instanceof Object); System.out.println(person instanceof Teacher); //System.out.println(person instanceof String);//编译失败 System.out.println("======================="); Student student = new Student(); System.out.println(student instanceof Student); System.out.println(student instanceof Person); System.out.println(student instanceof Object); //System.out.println(student instanceof Teacher);//编译失败 //System.out.println(student instanceof String);//编译失败 //Object > String //Object > Student > Person //Object > Teacher > Person } }
我们可以发现,对于A a = new B()[其中A是B的父类或A = B]中,如果A和B没有父子关系,那么编译失败。在后面的(a instanceof C)中如果B是C的子类或者B=C,那么返回值为true,否则返回值为false
先看例子:
package com.kuangshen.OOP; public class Application { public static void main(String args[]) { Person person = new Student(); ((Student) person).eat(); } }
当父类转化为子类时,要强制转换,本质原因是子类可以调用父类的方法,但父类不可以调用子类的方法。
注意点:
package com.kuangshen.OOP; public class Bus { private static int age; private double score; public void run() {} public static void go() {} public static void main(String args) { Bus bus = new Bus(); System.out.println(Bus.age);//对于静态变量,可以用类名直接调用。一般工作时尽量这样调用,方便知道这个age是静态变量。 //System.out.println(Bus.score);//报错 System.out.println(bus.age); System.out.println(bus.score); bus.run(); bus.go();//一般都是这样调用 //Bus.run();//这样会报错 Bus.go();//static的特性可以用类名直接调用 go();//由于main函数在类名中,所以可以前面不加类名直接调用,所以这种格式不能在别的.java文件中这样写 } }
package com.kuangshen.OOP; public class Bus { //顺序2:一般用来赋初值 { System.out.println("匿名代码块"); } //顺序1:只执行依次 static { System.out.println("静态代码块"); } public Bus(){ System.out.println("构造方法"); } public static void main(String args[]) { Bus bus1 = new Bus(); System.out.println("========="); Bus bus2 = new Bus(); } }
最终输出结果如下:
静态代码块
匿名代码块
构造方法
@@@@@@@@@@@@@@@@@@@@
匿名代码块
构造方法
如果一个类用了final关键字,就不能被继承。
package com.kuangshen.OOP; public final class Person { public void run() { System.out.println("Person"); } }
package com.kuangshen.OOP; public class Student extends Person{//这里会报错,无法继承有final关键字的(常量无法被继承) @Override public void run() { System.out.println("Student"); } public void eat() { System.out.println("eat"); } }
例子:
package com.kuangshen.OOP; public abstract class Action { public abstract void dosomething(); }
package com.kuangshen.OOP; public class ActionMain extends Action { //当一个子类继承了抽象类时会报错,必须要重写抽象方法。 //如果子类也是抽象类,那么要在子子类去重写抽象方法 @Override public void dosomething() { } }
抽象类的用处:比如你开发一个游戏,不同的游戏任务某项数据不一样,那么利用抽象类方法名不变,只需要在其继承中重写方法就可以了,本质是为了提高开发效率。
抽象类需要继承,由于java中都是单继承,所以泛用性大大降低;因为接口可以多继承,所以java中最常用到的是接口。
下面是userService.java,timeService.java,userServiceImpl.java的例子
package com.kuangshen.OOP.demo01; public interface UserService {//接口通过interface定义 public abstract void a();//在IDEA中,接口中的方法都默认公共并且抽象的,所以public和abstract可以不写 void add(); void delete(); void update(); void query(); }
package com.kuangshen.OOP.demo01; public interface TimeService { void timer(); }
package com.kuangshen.OOP.demo01; public class UserServiceImpl implements UserService, TimeService {//接口可以多继承 @Override public void a() { } @Override public void add() { } @Override public void delete() { } @Override public void query() { } @Override public void update() { } @Override public void timer() { } }
package com.kuangshen.OOP.neibulei; public class Outer { private int id = 10; public void out() { System.out.println("这是外部类的方法"); } public class Inner { public void in() { System.out.println("这是内部类的方法"); } //内部类可以获得外部类的私有属性 public void getID() { System.out.println(id); } } }
package com.kuangshen.OOP.neibulei;public class MainClass { public static void main(String args[]) { Outer outer = new Outer(); outer.out(); Outer.Inner inner = outer.new Inner();//内部类的定义方法 inner.in(); inner.getID(); }}
输出结果:
这是外部类的方法
这是内部类的方法
10