一、初识面向对象
面向过程&面向对象
面向过程思想
步骤清晰简单,第一步做什么,第二步做什么….
面对过程适合处理一些较为简单的问题
面向对象思想
-
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
-
面向对象适合处理复杂的问题,适合处理需要多人协作的问题!
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
面向对象编程(Object-Oriented Programming, OOP)
- 面向对象编程的本质就是:以类的方式组织代码,以对象的形式封装数据。
- 抽象:编程思想!持续的学习,茅塞顿开!多实践,多测试大脑中的想法!实践出真知~
三大特性:
- 封装
- 继承
- 多态
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
从代码运行角度考虑是先有类后有对象。类是对象的模板。
二、方法回顾和加深
- 方法的调用
- 静态方法
- 非静态方法
- 形参和实参
- 值传递和引用传递(回头再去看看
三、对象的创建分析
//学生类
public class Student {
//属性:字段
String name;//没有赋值,默认为null
int age;//没有赋值,默认为0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//一个项目应该只存一个main方法!
public class Application {
public static void main(String[] args) {
//类:抽象的,要实例化,实例化=new
//类实例化后会返回一个自己的对象!
//stu1对象就是一个Student类的具体实例!
Student stu1 = new Student();
stu1.name = "小明";
stu1.age = 8;
System.out.println(stu1.name);
System.out.println(stu1.age);
}
}
(构造器:构造方法)
public class Person {
//一个类即使什么都不写,它也会存在一个构造方法
String name;
int age;
//alt+fn+F12 = alt+insert 自动生成构造器
//无参:显示的定义构造器
public Person() {
}
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
//一个项目应该只存一个main方法
public class Application {
public static void main(String[] args) {
//new实例化了一一个对象
Person person = new Person("lff",18);
System.out.println(person.name);
System.out.println(person.age);
}
}
四、面向对象三大特性
- 封装
- 继承
- 多态
封装的优点
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护增加了
public class Student {
//类 private:私有
//属性私有
private String name;//名字
private char sex;//性别
//提供一些可以操作这个属性的方法!
//提供一些public 的get、set方法
//get获得这个数据 (生成getterseter快捷键alt+fn+f12)
public String getName() {
return name;
}
//set给这个数据设置值
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
//学习() 方法
//睡觉()
}
public class Applicant {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("lff");
System.out.println(s1.getName());
s1.setSex('M');
System.out.println(s1.getSex());
}
}
单继承:一个儿子只能有一个爸爸,一个爸爸有多个儿子
重写:改写
父类中不能被重写的方法有:
1.带static修饰的方法(static方法属于类,不属于实例)
2.带final修饰的方法(final常量修饰符)
3.带private修饰的类,私有类不能重写
//父类:B
//重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B==>test()");
}
}
//子类:A
public class A extends B{
//Override重写
@Override //注解:有功能的注释!
public void test(){
System.out.println("A==>test()");
}
}
public class Applicant {
public static void main(String[] args) {
//静态的方法和非静态的方法区别很大!
//方法的调用只和左边,定义的数据类型有关
A a = new A();
a.test();
//父类的引用指向了子类
B b = new A();
b.test();
/*
输出结果:
A==>test()
A==>test()
*/
/*
如果AB类中test前加static则
输出结果:
A==>test()
B==>test()
*/
}
}
即b是A new出来的对象,因此调用了A的方法,因为静态方法是类的方法,而非静态是对象的方法。
有static时,因为b是用b类定义的
没有static时,b调用的是对象的方法,而b是用A类new的
不是父子关系不能转换:报错:类型转换异常! ClassCastException!
父类引用指向子类对象:Father f1 = new Son();
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
Person s2 = new Student();//父类引用指向子类对象
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
//Student能调用的方法都是自己的或者继承父类的!
//Person父类型,可以指向子类,但是不能调用子类独有的方法(只能将父类强制转换成子类对象才能调用)
s1.run();
s2.run();//在父类new子类,调用时是调用父类,要是子类重写了父类,则调用子类方法 即没重写输出run
((Student) s2).eat();//父强制转子 s2.eat()会报错
/*结果为
son son eat
*/
}
}
public class Student extends Person{
@Override
public void run(){
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
public class Person {
public void run(){
System.out.println("run");
}
}
instanceof
public class Applicant {
//Object=>A Object=>B
public static void main(String[] args) {
Object ob = new B();
B b = new B();
System.out.println(ob instanceof A);//ob指向的是B,而A与B不是继承关系,因此结果是flase
System.out.println(ob instanceof B);
//System.out.println(b instanceof A); //B与A没有继承关系,所以编译错误
System.out.println(b instanceof B);
//b
}
}
编译是否通过:看类,即等号左边的
最终T/F:看指向的对象,即等号右边的
编译看左,运行看右
多态:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型; 强制转换
- 方便方法的调用,减少重复的代码!简洁
static
//static
public class Student {
public static int age;//静态变量 大多只会出现在多线程
private double score;//非静态变量
//下面这个是非静态方法
public void run(){
System.out.println("run");
//go();//非静态方法里可以调用静态方法
}
//下面这个是静态方法
public static void go(){
System.out.println("go");
}
public static void main(String[] args) {
Student s1 = new Student();
//静态变量对于类,所有对象(实例)所共享,当直接使用类名去调用变量名,说明这个变量名是static(静态)的
System.out.println(Student.age);
//System.out.println(Student.score);会报错,提示score是非静态变量,无法用类名调用。
System.out.println(s1.age);
System.out.println(s1.score);
System.out.println("========================");
/*
s1.run();(想使用run()方法,就必须new一个Student,即new一个对象,调用的写法只能是 对象名称.方法名)
go();(即使没有new一个Student,也可以直接调用go()方法,)
Student.go();(也可以在go()方法前面加类名,也可以像上面一样不加类名,(不加类名的前提是必须在同一个类下面))
*/
}
}
匿名代码块/静态代码块
package com.oop.demo09;
//当下面public class Person写成public final class Person时,表示当前类不能被继承
//final有最终的意思
public class Person {
//第二个执行,每new一次对象就会执行一次(可以用来赋初始值)
{
System.out.println("匿名代码块");
}
//第一个执行,并且只执行一次
static {
System.out.println("静态代码块");
}
//第三个执行,每new一次对象就会执行一次
public Person() {
System.out.println("无参构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("======");
Person person2 = new Person();
/*
输出结果:
静态代码块
匿名代码块
无参构造方法
======
匿名代码块
无参构造方法
*/
}
}
静态导入包
package com.oop.demo09;
//静态导入包~
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
//System.out.println(Math.random());//静态导入包的方法之后,连类名都可以不写了
System.out.println(random());
System.out.println(Math.PI);//这里没导入包的方法,所以要写Math
}
}
五、抽象类和接口
//abstract 抽象类
public abstract class Action {
//抽象即约束~有人帮我们实现~
public abstract void doSomething();//abstract,抽象方法,只有方法名字,没有方法的实现!
//1.不能new这个抽象类,只能靠子类去实现它;是个约束!
//2.抽象类中可以写普通的方法
//3.抽象方法必须在抽象类中
public void run(){//普通方法
System.out.println("run");
}
}
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法~(重写父类的方法),除非把这个类也设置为抽象类,再有它的子类实现
public class A extends Action {
@Override
public void doSomething() {
}
}
//interface 定义的关键字 接口都需要有实现类
public interface UserService {
//接口中的所有定义其实都是抽象的public abstract(省略了)
//只用写返回值类型+参数名+(参数有就写,没有就不写)
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
//默认是常量 public static final(省略了)
int AGE = 99;
}
public interface TimeService {
void timer();
}
普通类UserServiceImpl实现
//抽象类 extends 只能单继承
//类可以实现接口 implements 接口名 (implement可以多实现,也叫多继承)
//实现了接口的类,就需要重写接口中的方法
//在第一行 按alt+enter自动生成重写
public class UserServiceImpl implements UserService,TimeService {
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
接口的作用
1.约束
2.定义一些方法,让不同的人实现~
3.public abstract 成员方法
4.public static final 成员变量
5.接口不能被实例化,接口中没有构造方法
6.implements可以实现多个接口
7.必须要重写接口中的方法~
接口和抽象类的区别
1. 接口多继承,抽象类单继承
2. 接口没有构造方法,抽象类有构造方法
3. 接口只有抽象方法,抽象类中也可以有普通方法
六、内部类
https://www.kuangstudy.com/bbs/1498295620027744257#header10