1、什么是面向对象
面向对象的本质:以类的方式组织代码,以对象的形式封装数据。
2、回顾方法的定义
3、方法的调用
(1)静态方法(static)
可以直接用“类名.方法”名调用
(2)非静态方法(没有static)
需要实例化new一下这个类:对象类名 对象名 = new 对象类();在idea中也可以直接:new 类名.方法名
(3)方法之间调用
当a()和b()都是普通方法时,可以直接调用;当a()和b()都是静态方法时,也可以直接调用;当a()是静态,b()不是静态,则a()不能直接调用b();
因为static是和类一起加载的,类存在是它就存在了,但是普通方法是类实例化时才存在,已存在的不能调用还没存在的。
(4)形参和实参
实参和形参的类型要一一对应
(5)值传递和引用传递
最后结果:
1
1
由上可知,java是值传递,不是引用传递。main中使用change()想改变a的值,但是并没有改变成功,就是因为java是值传递,如果是引用传递的话,就成功了,因为名字可以一样,但是引用的地址是唯一的。
注:引用传递对象**,本质还是值传递**
结果:
null
秦疆
4、类与对象的创建
1、一个项目应该只存在一个main方法,不要在每个类中都写一个main;
2、一个类中只有:属性 字段 和 方法()
3、类是抽象的,用的时候需要实例化(new 类名)一下;实例化之后会返回一个自己的对象,这个返回的对象可以是任意的名字;
5、构造器详解
1、一个类及时什么都不写,默认也会有一个构造方法(构造器),这个方法和类名相同,且里面什么都没有。这样的话别的类调用这个类的参数属性时,就可以new一下调用了。
2、可以手动显示定义构造器,用来实例化初始值如下,此时再实例化new这个类时,就默认将name定义为“qinjiang”;
3、有参构造:一旦定义了有参构造器,无参构造器就必须手动显示定义
4、使用new关键词,本质上实在调用构造器
5、在idea中,alt+insert可以自动生成构造器。
总结
构造器:
1、和类名相同
2、没有返回值
作用:
1、new本质在调用构造器
2、初始化对象的值
注意点:
1、定义有参构造之后,如果想使用无参构造,手动显示的定义一个无参的构造器
2、快捷键:alt+insert
3、this. 代表的是本类的东西
this
this.属性名称 : 指的是访问类中的成员变量,用来区分成员变量和局部变量(重名问题)
class Person{
private String name;
private int age;
private String gender;
Person(){}
Person(String name,int age,String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
}
6、创建对象内存分析
7、简单小结类与对象
1、类是一个模板:抽象,对象是一个具体的实例;
2、属性:字段 成员变量
默认初始化
数字:0 0.0
char: u0000
boolean:false
引用:null
8、封装
关键字:private(私有)
1、属性私有:
2、提供一些public的get、set方法:
//get 获得这个数据
public String getName(){
return this.name;
}
//set 给这个数据设置值
public String setName(String name){
this.name = name ;
}
注:可以使用alt+insert自动生成get/set方法
自动生成下面的get/set方法:
可以在内部的封装中设置一些规则,让程序更安全,比如年龄:
这样在另一个类中调用的时候就不能随心所欲的设置年龄了
封装的意义:
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、提高系统的可维护性
8、继承(父子关系)
比如有个类为Person()人**(父类/基类)** ,那么Teacher()老师类和Student()学生类都是其子类(或派生类),即Teacher is Person
1、子类可以继承父类的所有public的方法和属性,子类虽然可以继承父类的私有属性,但是不能直接访问私有属性,除非父类开放了私有属性的访问接口(所以默认说私有无法被继承)。
子类不能完全继承父类的所有方法和属性
1 若子类和父类在同一个包内,子类可以继承父类中访问权限设定为public、 protected、 default的成员变量和方法,除了private都可以。
2 若子类和父类不在同一个包内,子类可以继承父类中访问权限设定为public、 protected的成员变量和方法。
换言之:
1、public、protected类型的属性或方法一定可以被继承
2、defalut 类型要看子类是否和父类在一个包。
2、快捷键:ctrl+H :打开继承关系图(展开到当前快捷键的子类)
3、在java中,所有的类都直接或间接继承Object类
4、java中只有单继承,没有多继承!(儿子只能有一个爸爸)
10、super
this:当前类的属性或方法
super:父类的属性或方法
啥都没有:当前方法的属性或形参或方法
子类调用父类的属性:
子类调用父类方法:
所以当调用本类的方法或属性时,最好都加上this,这样不容易弄混。
下面代码我们可以得出,当new一下子类时,首先会调用父类的构造器,然后再调用子类构造器。由此我们可以得出,子类构造器第一行一定是有一行隐藏代码:super();
并且,当父类没有无参构造器,即只有有参构造器时,子类也无法写无参构造,但是可以调用父类的有参构造器。所以要封装的时候,只要重写了有参构造器,那最好一并写上无参构造器。
super注意点:
1、super调用父类的构造方法,必须在构造方法的第一个(第一行);
2、super必须只能出现在子类的方法或者构造方法中;
3、super和this不能同时调用构造方法;
super对比this
-
代表的对象不同:
this:本身调用这个对象
super:代表父类对象的引用 -
前提:
this:没有继承也可以使用
super:只能在继承条件下才可以使用 -
构造方法:
this()调用的本类的构造
super()调用的是父类的构造。
11、方法重写(Override)
重写都是方法,和属性无关。
1、静态方法的调用只和左边定义的数据类型有关,但是这不算重写,例子如下:
2、非静态方法就和上面的不一样了:
3、重写的方法关键词只能是public
4、重写的快捷键,在子类中:alt+insert
然后就自动出现重写的代码:默认调用了父类的方法test()
我们可以在重写的代码里重写自己的内容:
总结
1、需要有继承关系,子类重写父类的方法。
2、方法名必须相同;
3、修饰符范围可以扩大,但是不能缩小:比如父类是private,子类可以重写为public(Public>Protected>Default>private)
4、抛出的异常范围可以被缩小,但不能被扩大:ClassNoteFoundException<Exception
5、重写,子类的方法和父类要一致,但是方法体不同。
为什么要重写:
1、父类的功能,子类不一定需要,或者不一定满足。
12、多态
一个对象的实际类型是确定的,但是可以指向的引用类型就不确定了(父类的引用指向子类,即通过父类去new子类)。
- 如果父类的引用指向子类,在调用时,当父类中有方法,子类中没有重写的对应方法,那会执行父类的那个方法:
(结果为run)
- 如果子类重写了父类的方法,那么父类的引用再指向子类时,会执行子类的重写的方法:所以下面的例子都指向了子类的重写后的方法run()
- 注:
1、对象能执行哪些方法,主要看对象左边的方法,和右边的关系不大!
2、子类能调用的方法都是自己的或者继承父类的。
3、父类能虽然可以指向子类,但是不能调用子类独有的方法。
多态存在的条件
1、有继承关系
2、子类重写父类方法
3、父类引用指向子类对象:Father f1 = new Son();
-
不能被重写的方法:
1、static方法,属于类,它不属于实例
2、final 常量
3、private方法 -
动态编译的意思:子类重写了父类的方法,父类引用指向父类,执行的时候才知道调用的是子类的方法而不是父类的。
13、instanceof和类型转换
instanceof
instanceof判断两个对象是不是有父子关系或本身,有就是true,没有就是false。
它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
初步理解,不一定对:
上述例子得出:编译报不报错看
左边的类与公式instanceof右边的类是否有关系;结果对不对看
右边的类与公式右边instanceof的类有没有亲缘关系。
类型转换
-
高转低:
但是此时的student不能直接用Student()类中的方法,所以需要类型转换一下,将这个Person类型的student对象转换为Student类型的student对象:(Student)student; ==> Student student = (Student) student;
现在就是将Person类型的student对象转换为Student类型的student对象了 -
低转高:不需要转,因为子类本来就已经继承了父类的所有方法,不会丢失原本的方法,可以直接调用。
14、static关键字
-
静态变量:又称类变量,是可以直接用类名去调用,而不用new:
由上面的代码可以看到,age为静态变量,可以直接用Student类调用;而score是非静态变量,所以只能先实例化对象,然后用对象去调用。 -
静态方法:和上述的静态变量一样,可以直接用类名调用,甚至可以什么都不用就直接用。但是非静态变量就需要先实例化对象再调用。
-
静态代码块:类加载的时候执行,是第一个执行的,且只执行一次
类执行顺序:1.静态代码块;2.匿名代码块;3.构造方法
注意:静态代码块只执行一次,当反复执行类时,会跳过静态代码块:
匿名代码块可以用来赋初始值
- 静态导入包:导包时添加static关键字,使被导入类中的静态方法/静态变量在当前类可直接调用,而无需使用类名加点的方式
(1)未使用静态导入:
public static void main(String[] args) {
//调用math类中的random()方法生成随机数
System.out.println(Math.random());
}
未使用静态导入时,需要通过类名Math加具体方法名random()来进行调用生成随机数
(2)使用静态导入:
import static java.lang.Math.random;
public class Demo {
public static void main(String[] args) {
//无需类名,直接通过random()方法生成随机数
System.out.println(random());
}
}
15、抽象类
1、抽象类不能被new实例化,只能被继承。
2、抽象方法必须在抽象类中,但是抽象类中可以写普通方法,也可以没有抽象方法
3、抽象的其中一个意义是约束
16、接口(interface):抽象类的抽象
面向接口编程,约束和实现分离
接口的本质是契约!
接口语法:public interface xxxx{ }
接口中方法的定义都是抽象的public abstract,并且在idea中,接口里的方法默认都是public abstract的,所以不用写这两个关键字,直接写方法。
接口都有实现类,且必须重写接口里的方法:
一般实现类是用“接口名+Impl”命名的
接口里面的重写可以用快捷键:点接口名按“alt+insert”
实现了接口的类,就必须重写接口的方法
利用接口实现多继承:
再写一个TimeService接口
接口中属性的定义也是默认的:都是静态常量,但是很少这么用
同上面的方法一样,public static final是默认存在的,可以不写。(方法只默认了public static,没有final)
17、内部类
用外部类对象来new内部类;当然out.new.Inner();是快捷输入,正规输入应该是Outer.Inner inner = outer.new Inner();
内部类作用:可以获得外部类的私有方法和属性
静态内部类(加个static)
当然还有其他的变形的内部类:下面这种方式可以用来在下面的class类中写测试方法,因为class类中可以写main方法。
但是一个类中只能有一个public class,但可以有多个class
还有在方法中写的局部内部类:
还有没有名字的内部类:其实就是没有名字的实例化对象,new之后直接调用