Java的核心思想就是OOP(Object-Oriented Programming)
面向过程:
面向对象:
面向对象的本质:以类的方式组织代码。以对象的形式组织(封装)数据
抽象:把一个系统的共同特点抽象抽取出来
【编程思想,持续学习,茅塞顿开!多实践,多测试大脑中的想法】
三大特征:
从认识论的角度理解:先有对象,后有类【从很多对象中抽象出来的特征,形成类】。对象,是具体的事物。类,是抽象的,是对对象的抽象。
从代码运行的角度考虑:先有类,后有对象【先设计一个类,再生成对象,用new关键字】。类是对象的模板。
// 读文件时抛出输入输出异常 public void readFile(String file) throws IOException{ }
静态方法(static)和非静态方法
// 对于静态方法 Student.say(); //类名.方法名() // 对于非静态方法 // 首先,将类实例化,通过new关键字 new.Student.say(); // new.类名.方法名() // 常规写法 Student student = new Student(); // 对象类型 对象名=对象值 student.say();
实际参数和形式参数
值传递和引用传递
this关键词:代表当前的类或者当前这个对象
类:
一种抽象的数据类型。对某一类事物的整体描述/定义,并不代表某一个具体的事物
Person类、Pet类等,描述/定义某一类具体事物所具备的特点
一个类中,只存在两种内容
public class Student{ // 属性:字段 String name; int age; // 方法 public void study(){ System.out.println(this.name+"is studying!"); } }
对象:
【规范】:在写程序时,不要在每个类中都写main方法。一个程序中只有一个main方法,可以定义一个大的启动类(可以叫Application类),并把它放到一边,便于我们随时启动测试
public class Application{ public static void main(String[] args){ // 类:抽象的,先实例化。实例化后会返回一个自己的对象 // student对象就是一个Student类的具体实例 // 这里的Student()就是构造方法 Student student = new Student(); // 这就叫:以对象的形式封装数据 student.name = "xiaoming"; student.age = 3; } }
public class Student{ // 属性:字段Field 成员变量 /* 初始值: 数字:0 0.0 char: u0000 boolean: false 引用:null */ String name; int age; // 方法 // 一个类即使什么也不写,也存在一个构造方法 // 显式定义构造方法 public Student(){ this.name = "xiaoming"; } // 有参构造 publiv Student(String name){ this.name = name; } public void study(){ System.out.println(this.name+"is studying!"); }
程序设计的目标:高内聚、低耦合,就是说类内部的数据操作细节自己完成,不允许外部干涉;仅暴露少量的方法给外部使用
定义:就是数据的隐藏。通常应该禁止直接访问一个对象中的数据的实际表示,而应该通过操作接口来访问。
做法:属性私有(private),get/set
意义:
【规范】
// 启动类 public class Application { public static void main(String[] args) { Student student = new Student(); // 属性是私有(private)的无法直接用student.name这样的方式进行调用 // 公有(public)的可以用student.name这样的方式进行调用 // 【对于外部类来说,内部类依然可以调用】 s s = new s(); int name = s.name; student.setName("xiaoming"); System.out.println(student.getName()); } public static class s{ private int name; } } public class Student { //属性私有 private String name; private int age; private char gender; // 提供一些可以操作这个属性的方法:public的get和set方法。也就是接口方法 // get方法,获取这个数据 public String getName() { return name; } // set方法,给这个数据设置值 public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { // 可以在set中加入条件判断 if (age > 120 || age < 0){ this.age = 3; }else{ this.age = age; } } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } }
定义:本质是对某一批类的抽象,从而实现对现实世界更好的建模
方法:使用extends关键字。子类是父类的扩展
功能:
// 学生 is 人: 派生类(父类),子类 public class Person { public Person(){ System.out.println("Person的无参构造"); } public int money = 10; protected String name = "xiaoli"; public void say(){} public void print(){ System.out.println("person"); } } public class Student extends Person{} public class Teacher extends Person{ public Teacher(){ super(); // 继承中的这一行代码被隐藏了。并且这一代码必须放在子类构造器的第一行 System.out.println("Teacher的无参构造"); } private String name = "xiaoming"; public void print(){ System.out.println("teacher"); } public void test(String name){ System.out.println(name); // xiaofang System.out.println(this.name); // xiaoming System.out.println(super.name); // xiaoli } public void test1(){ print(); // teacher this.print(); // teacher super.print(); // person } } public class Application { public static void main(String[] args) { Teacher teacher = new Teacher(); // 输出:Person的无参构造\nTeacher的无参构造 teacher.say(); teacher.test("xiaofang"); } }
Java中只有单继承,没有多继承(一个儿子只能有一个爸爸,extends后只能有一个类,但是可以一个爸爸可以有多个儿子,多个类extends同一个类)
在java中,所有类都默认继承object类
super,与this相对应,表示父类。只有存在继承才可以使用
注意:
super()调用父类的构造方法必须放在子类构造器或者子类方法的第一行
this()和super()不能同时存在,因为都要求放在第一行
若父类中存在有参构造没有无参构造,则不能调用super(),并且要写上super(参数),否则会报错
定义:子类重写父类的方法
要求:子类的方法与父类的方法必须要一致,但方法体不同
方法:alt + insert -> override
为什么需要重写:
注意:
【修饰符的范围:public > Protected > Default > private】
IDEA中,代码左边栏中的O代表重写(overwrite method)
public class B{ public static void test(){ System.out.println("B"); } public static void testAgain(){ System.out.println("B"); } } public class A extends B{ public static void test(){ System.out.println("A"); } // @Override表示重写 @Override // 注解:有功能的注释 public static void testAgain(){ System.out.println("A"); } } public class Application{ public static void main(String[] args){ // 方法的调用只和左边定义的数据类型有关 // 对于static方法,方法属于类,它不属于实例 A a = new A(); B b = new A(); // 我理解的是子类的构造器会首先运行父类的构造器,因此可以如此定义。 // 并且对于静态方法,可以直接通过类来访问,因此输出结果为A a.test(); // A // 父类的引用指向子类 b.test(); // B // 对于非static方法,子类的重写会重写父类的方法 a.testAgain(); // A b.testAgain(); // A } }
重写与重载的区别:
public class Person { public void say(){ System.out.println("i am a person"); } } public class Teacher extends Person{ @Override public void say() { super.say(); System.out.println("i am a teacher"); } } public class Application { public static void main(String[] args) { Teacher te1 = new Teacher(); // 父类的引用指向子类 Person te2 = new Teacher(); Object te3 = new Teacher(); // 对象执行哪些方法,主要看对象左边的类型,和右边关系不大 // 子类可以调用自己或者继承自父类的方法 te2.say(); // 方法被重写 te1.say(); // 父类可以指向之类,但是不能调用子类独有的方法 // te3.say(); // 报错,因为Object类中没有这一方法 ((Teacher) te3).say(); // (Teacher) te3强制类型转换,可以由父类转换成子类(高到低) } }
条件:
注意:
用于判断两个变量之间有无父子关系
public class Person { public void run(){ System.out.println("run"); } } public class Teacher extends Person{ public void go(){ System.out.println("go"); } } public class Student extends Person{} public class Application { // Object > String // Object > Person > Teacher // Object > Person > Student public static void main(String[] args) { Object te3 = new Teacher(); System.out.println(te3 instanceof Teacher); // true System.out.println(te3 instanceof Person); // true System.out.println(te3 instanceof Object); // true System.out.println(te3 instanceof Student); // false System.out.println(te3 instanceof String); // false Person te2 = new Teacher(); System.out.println(te2 instanceof Teacher); // true System.out.println(te2 instanceof Person); // true System.out.println(te2 instanceof Object); // true System.out.println(te2 instanceof Student); // false // System.out.println(te2 instanceof String); // 编译错误 Teacher te1 = new Teacher(); System.out.println(te1 instanceof Teacher); // true System.out.println(te1 instanceof Person); // true System.out.println(te1 instanceof Object); // true // System.out.println(te1 instanceof Student); // 编译错误 // System.out.println(te1 instanceof String); // 编译错误 // 类型之间的转换 // 基本类型转换:高转低需要强转,低转高则不需要 // 类之间的转换(父类与子类):高转低需要强转,低转高则不需要(同理) // 高 低 Person te = new Teacher(); // 子类转父类可能会丢失一些方法 // te.go(); // 报错,父类无法执行子类中的方法,因此要进行转换 Teacher t = new (Teacher) te; t.go(); ((Teacher) te).go(); } }
类转换的作用:方便方法的调用,减少重复的代码。简洁
使用总结:
public class Application { { // 匿名代码块,在构造器之前执行,无法主动调用 } static { // 静态代码块,在构造器之前执行,只执行一次(在匿名代码块之前执行) // 应用:赋初值 } private static int age; private double score; // 非静态方法可以调用静态方法 public void run(){ go(); } public static void go(){ // run(); // 报错 } public static void main(String[] args) { Application stu = new Application(); System.out.println(stu.age); System.out.println(stu.score); System.out.println(Application.age); // System.out.println(Application.score); // 报错 stu.run(); stu.go(); // Application.run(); // 报错 Application.go(); go(); // run(); // 报错 } }
其他应用:
// 静态导入包 import static java.lang.Math; // import static java.lang.Math.random; public class Application { public static void main(String[] args) { // System.out.println(Math.random()); // 通过静态导入包来进行替代写法 System.out.println(random()); } }
不能被继承(inherent)
public final class Person{} public class Student extends Person{} // 报错
abstract修饰符。
抽象类中可以没有抽象方法,但是存在抽象方法的类一定要声明为抽象类
抽象类,不能使用new关键字来创建对象,它的应用场景在于被子类继承
抽象方法,只有方法的声明,没有方法的实现,它的应用场景在于被子类实现
子类继承抽象类,那么就被需要实现抽象类中没有实现的抽象方法,否则该子类也要被声明为抽象类
抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super()或super(参数列表)调用抽象类中的构造方法。
应用:为后续的操作做一个规范,把后面的一些公有属性抽象出来,避免反复进行操作。总之,就是为了提高开发效率,提高可扩展性
【理解:抽象类就是提供一个框架,让你后续的操作沿着框架进行】
public abstract class Person { // 作为一个约束,让别人帮助实现 public abstract void doSomething(); public void done(){} } public class Teacher extends Person{ @Override public void doSomething() {} }
存在的意义:类只能单继承,因此有一定的局限性,为了克服这种局限性,使用多继承的接口
定义:提供一种规范,类似于现实世界中”如果你是……你必须……“的思想。
本质:一种契约,类似法律,大家都要遵守并执行
普通类、抽象类、接口的区别
声明接口:用关键字interface
public interface Person { // 作为一个约束,让别人帮助实现,接口必须有实现类 void doSomething(); // 默认隐藏public abstract void go(String name); } public interface Student{ // 一般不定义常量 String name = "xiaoming"; // 常量默认隐藏public static final void cry(); } // 类通过implements实现接口 public class Teacher implements Person,Student{ @Override public void doSomething() {} @Override public void go(String name) { } @Override public void cry() { } }
public class Out { private int id; public void out(){ System.out.println("this is out"); // 局部内部类: 在方法中 class inner2{} } class Inner1{ public void in(){ System.out.println("this is in"); } // 成员内部类 // 获取外部类的私有属性和方法 // 同样的,若内部类为static(静态内部类)则无法获得外部类的属性和方法 public void getID(){ out(); System.out.println(id); } } } // 一个java中可以有多个class,但只能有一个public class class A{ } public class Application { public static void main(String[] args) { Out out = new Out(); // 通过这个外部类来实例化内部类 Out.Inner1 inner = out.new Inner1(); inner.in(); inner.getID(); // 匿名内部类 new Apple().eat(); Service hello = new Service() { @Override public void hi() { System.out.println("hello"); } }; } } class Apple{ public void eat(){ System.out.println("good"); } } interface Service{ void hi(); }