java面向对象编程
1. 1、什么是面向对象
本质:以类的方式组织代码,以对象的组织(封装)数据
三大特性:封装、继承、多态
2. 2、面向对象
静态方法
package OOP;
public class Demo02 {
//静态方法 static
public static void main(String[] args) {
Student.say();
}
//非静态方法
}
public class Student {
public static void say(){
System.out.println("Hello World");
}
}
非静态方法,需要实例化 学生这个类
package OOP;
public class Demo02 {
//静态方法 static
//非静态方法
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}
3. 3、创建对象与初始化对象
Application.java
package OOP.demo05;
public class Application {
public static void main(String[] args) {
Student student =new Student();//实例化对象
Student xiaoming =new Student();
Student xiaohong =new Student();
xiaoming.name="小明";
xiaoming.age=18;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
Student.java
package OOP.demo05;
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法:函数
public void study(){
System.out.println(this.name+"正在学习");
}
}
4. 4、构造器详解
构造器也叫构造方法
一个类即使什么都不写 也会存在一个方法(构造方法)
构造方法满足 1、与类名相同 2、无返回值
4.1. 构造器的作用
1、使用new关键字,必须要有构造器
2、构造器一般用于初始化值
5. 5、内存分析
6. 6、封装
白话:该露的露,该藏的藏
专业:我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏)
在定义一个对象的特性的时候,有必要决定这些特性的可见性,即哪些特性对外部是可见的,哪些特性用于表示内部状态。通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
使用private 修饰需要封装的成员变量
private无法直接调用赋值
但可以用设置的公共方法对其进行操作
package OOP.demo06;
public class Student {
private String name;
private int age;
private int id;
private String sex;
//提供一些方法用于对这些私有属性进行操作
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
赋值
package OOP.demo06;
public class Application {
public static void main(String[] args) {
Student xiaoming =new Student();
xiaoming.setName("小明");
System.out.println(xiaoming.getName());
}
}
还可以用alt+insert 快速设置属性的 Get set方法
6.1. 封装的意义 好处
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、提高程序的可维护性
7. 7、继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
为什么需要继承?继承的作用? 第一好处:继承的本质在于抽象。类是对对象的抽象,继承是对某一批类的抽象。
第二好处:为了提高代码的复用性。
extands的意思是“扩展”。子类是父类的扩展。
定义‘人’类
package OOP.Demo07;
public class Person {
String name;
int age;
}
继承
package OOP.Demo07;
public class Student extends Person{
}
其中 Person为父类 ,Student为子类(派生类)
这里只能继承公有的 属性,方法
在java中,所有的类,都默认直接或者间接继承Object类
java中只有单继承 没有多继承(一个儿子只能有一个爹,但一个爹可以有多个儿子)
8. 8、继承-super
不管是显式还是隐式的父类的构造器,super语句一定要出现在子类构造器中第一行代码。所以this和super不可能同时使用它们调用构造器的功能,因为它们都要出现在第一行代码位置。
【super使用的注意的地方】
- 用super调用父类构造方法,必须是构造方法中的第一个语句。
- super只能出现在子类的方法或者构造方法中。
- super 和 this 不能够同时调用构造方法。(因为this也是在构造方法的第一个语句)
【super 和 this 的区别】
- 代表的事物不一样:
- this:代表所属方法的调用者对象
- super:代表父类对象的引用空间。
- 使用前提不一致:
- this:在非继承的条件下也可以使用。
- super:只能在继承的条件下才能使用。
- 调用构造方法:
- this:调用本类的构造方法。
- super:调用的父类的构造方法
9. 9、继承-方法重写
条件
- 方法重写只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被重写.
- 静态方法不能重写
- 父类的静态方法不能被子类重写为非静态方法 //编译出错
- 父类的非静态方法不能被子类重写为静态方法;//编译出错
- 子类可以定义与父类的静态方法同名的静态方法(但是这个不是覆盖)
- 私有方法不能被子类重写,子类继承父类后,是不能直接访问父类中的私有方法的,那么就更谈不上重写了。
重写的语法
- 方法名必须相同
- 参数列表必须相同
- 访问控制修饰符可以被扩大,但是不能被缩小: public protected default private
- 抛出异常类型的范围可以被缩小,但是不能被扩大 ClassNotFoundException ---> Exception
- 返回类型可以相同,也可以不同,如果不同的话,子类重写后的方法返回类型必须是父类方法返回类型的子类型
10. 10、什么是多态
10.1. 多态的存在条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
注:多态是方法的多态,属性没有多态性
s2是父类Person的引用,其创建了一个Student类的实例,这里由于父类中没有eat()方法,所以s2.eat()是无法成功的。
当父类中有eat方法时,如果子类没有重写方法,则会调用父类中的方法,重写则调用子类的方法
但是也可以通过强制转换来执行eat方法
Application.java
package OOP.demo09;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
// new Student();
// new Person();
//但可以指向的引用类型是不确定的
Student s1 =new Student();
//父类的引用指向子类的对象
Person s2 =new Student();
// 但是不可以用子类的引用指向父类的对象
// Student s3 =new Person();
Object s4 =new Student();
s1.run();
s2.run();
s1.eat();
// s2.eat();
((Student)s2).eat();
}
}
Student.java
package OOP.demo09;
public class Student extends Person {
//重写父类run方法
@Override
public void run() {
System.out.println("学生正在跑步");
}
public void eat(){
System.out.println("学生正在吃饭");
}
}
Person.java
package OOP.demo09;
public class Person {
public void run(){
System.out.println("run");
}
}
10.2. 多态注意事项
- 多态是方法的多态,属性没有多态
- 父类与子类有联系, 类型转换异常 ClassCastException
- 存在条件: 继承关系 执行了子类的方法,父类的引用指向子类对象
11. 11、instanceof 与 类型转换
11.1. instanceof : 可以判断一个对象是什么类型
这里创建了三个类,父类Person 子类1 Student 子类2 Teacher
package OOP.demo10;
public class Application {
public static void main(String[] args) {
Object object =new Student();
//Object -> Person -> Student
//Object -> Person -> Teacher
//Object -> String
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof String);//false
System.out.println(object instanceof Teacher);//false
System.out.println("==================");
//Object -> Person -> Student
//Object -> Person -> Teacher
Person person =new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
// System.out.println(person instanceof String); 编译报错
System.out.println(person instanceof Teacher);//false
System.out.println("==================");
//Object -> Person -> Student
Student student =new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
// System.out.println(student instanceof String); 编译报错
// System.out.println(student instanceof Teacher); 编译报错
}
}
其中绿色的就是关系表,如果两者有关系(在一条关系链上) 那么就会返回true,
由于都是Student类的实例,则其主要关系链 就一定含有Student
true:二者在主要关系链上(**标粗绿色的**)
flase:二者不在主要关系链上,但存在另外的关系链(没有标粗绿色的)
编译报错:二者无关系链
11.2. 强制类型转换
public class Application {
public static void main(String[] args) {
// 高 低
Person student =new Student();
// student.go(); 无法执行
((Student)student).go(); //强制类型转换为Student类型
}
}
- 父类引用指向子类对象
- 把子类转换为父类,向上转型
- 把父类转换为子列,向下转型,强制转换
- 方便方法的调用,减少重复的代码,更加简洁
12. 12、 static关键词
- static加在方法上 就是静态方法;加在属性上,就是静态属性
12.1. 非静态方法可以调用静态方法
public class Student {
private static int age;//静态变量
private double score;//非静态变量
public static void main(String[] args) {
go();
//run(); 无法运行
}
public void run(){
go();
}
public static void go(){
System.out.println("go");
}
}
静态方法会与类一起加载,但非静态方法不会,所以 run();编译错误
非静态方法run 调用了静态方法 go
12.2. 匿名代码块与静态代码块
public class Person {
{
//代码快(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
}
12.3. 执行顺序
package OOP.demo11;
public class Person {
{
//代码快(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person = new Person();
}
}
输出
静态代码块
匿名代码块
构造方法
观察输出可以发现,先执行了静态代码块 然后执行匿名代码块 再执行构造方法
注:静态代码块只会执行一次
例子
package OOP.demo11;
public class Person {
{
//代码快(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("=================");
Person person2 = new Person();
}
}
输出
静态代码块
匿名代码块
构造方法
=================
匿名代码块
构造方法
可以发现输出第二次构造方法时,没有执行静态代码块
静态代码块只会在第一次执行时最开始运行
12.4. 静态导入包
如下代码
import java.lang.Math;
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
我希望直接使用 random() 而不用加上 Math.
则可以通过静态导入包实现
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(random());
}
}
import static java.lang.Math.random; 就是静态导入包
13. 13、抽象类
13.1. abstract 抽象类
public abstract class Action {
}
13.2. abstract 抽象方法
public abstract class Action {
//约束~有人帮我们实现
//abstract 抽象方法,只有方法名字,没有方法实现
public abstract void doSomething();
}
当我们设置了抽象方法后,使用另外一个类继承这个类时,则
必须重写抽象方法 或者将子类也设置为抽象类
13.3. 抽象类的特点
- 不能new这个抽象类,只能靠子类去实现他;约束!
- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
13.4. 抽象的意义
- 抽象出来,提高开发效率
14. 14、接口的实现与定义
14.1. 普通类 抽象类 接口
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有!
- 接口:只有规范!
14.2. 接口的本质
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
- 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
14.3. 接口的定义与实现
用接口定义增删改查
public interface UserService {
//接口中所有定义都是抽象的 public abstract
void add();
void delete();
void update();
void query();
}
只写了接口,还需要一个类来实现接口里面的方法,这里用到关键字implements
package OOP.demo13;
//类可以实现接口 用implements关键字
//对比抽象类 单继承 extends
public class UserServiceImpl implements UserService {
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void query() {
}
}
实现了接口的类,就要重写接口中的方法
14.4. 实现多个接口的类(接口实现多继承)
除了UserService 接口
我们新建一个接口 取名TimeService
package OOP.demo13;
public interface TimeService {
void timer();
}
我们可以在一个类里面实现多个接口
只需要将多个接口用逗号分开 并实现其方法即可
14.5. 接口的作用
- 约束
- 定义一些方法,让不同的人实现
- 接口不能被实例化(接口中无构造方法)
- 可以用Implements 实现多个接口
- 必须要重写接口中的方法
15. 15、内部类
例子:A类中再定义一个B类 (套娃)
package OOP.demo14;
public class Outer {
private int id ;
public void out(){
System.out.println("outer");
}
class Inner{
public void in(){
System.out.println("inner");
}
}
}
15.1. 通过外部类调用内部类
public class Application {
public static void main(String[] args) {
//new
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
15.2. 获取外部类的私有属性
一个java类中可以有多个class类,但只能有一个public class










