1. 何为面向对象
1. 面向过程
思想:第一步,第二步,第三步 按照一定的步骤执行
2. 面向对象
思想:先将问题分类解决,最后对某个分类下面向过程思考。
面向对象编程(OOP)的本质:
-
以类组织代码,以对象组织数据。
-
类的核心是:抽象;对象的核心是:实例化
面向对象的三大特性:
- 封装:
- 继承:
- 多态:
2. 方法回顾
1. break和return的区别
- break 跳出switch结束循环
- return是返回一个值,结束方法体
2. 静态方法和非静态方法
package com.liang.OOP;
public class Student {
//静态方法 是和类一起加载的,即类存在时它就存在
public static void say(){
System.out.println("说了一句");
a(); //因为同为一起加载的静态方法,所有可以调用
}
//非静态方法 是通过对象调用才加载
public void say2(){
System.out.println("说了第二句");
b();//因为用为一起加载,所以可以调用
}
//静态方法2
public static void a(){
}
//非静态方法2
public void b(){
System.out.println("调用成功");
}
}
------------------------------------------------------
package com.liang.OOP;
public class Demo01 {
public static void main(String[] args) {
//调用静态方法 类名.方法
Student.say();
//调用非静态方法 new一个对象.方法
Student student = new Student();
student.say2();
//第二种形式
new Student().say2();
}
}
----------------------------------
说了一句
说了第二句
调用成功
说了第二句
调用成功
3. 类和对象的创建和分析
1. 一个类只能有一个Public
public class Demo01 {
public static void main(String[] args) {
}
}
class a{
}
2. 类和对象的关系
- 类是一种抽象数据类型(人一个类)
- 对象是类的实例化(小明是人这个类的实例化)
public class Demo01 {
public static void main(String[] args) {
person XiaoMing = new person();//实例一个person类 叫小明
System.out.println(XiaoMing.name);//实例出来的小明种的name为初始值null
XiaoMing.change("en");//调用方法this.name赋值,也是赋给xiaoming这个实例下name的值
System.out.println(XiaoMing.name);
}
}
class person{
String name;
public String change(String name){
this.name=name;
return name;
}
}
3. 对象的创建和初始化
- 使用new关键字创建对象
本质:分配一个空间,且调用类中构造器初始化该对象
4. 构造器(构造方法)
- 类中的构造方法是创建对象必须调用的,有以下特性:
- 构造方法必须与类名相同
- 必须没有返回类型且不能写void
/*
构造器的作用:
1.使用new必须要有构造器,new本质是调用构造器
2.用来初始化值
构造器:
1.有参构造,定义了有参构造后想使用无参就必须显式定义无参构造
2.无参构造
*/
public class Person {
String name;
//显式定义无参构造
public Person() {
}
public Person(String name) {
this.name = name;
}
}
-
IDEA快速生成构造方法
alt+insert+Constrauctor(无参即为selete none)
4. 对象的内存分析
5. 封装
1.简介
- 封装(数据的隐藏)
禁止访问一个对象的数据实际表示,而是用过一些接口来访问,即为信息的封装
-
封装的思想
程序设计追求**“高内聚,低耦合”**,“高内聚”即为类的内部数据操作自己完成;“低耦合”即为暴露少量的方法给外部使用。
-
面向对象封装具体操作:属性私有,get/set
6. 继承
1. 简介
-
继承使用关键字 extends
class A extends B{ }
即B为A的父类 A是B的子类 A享有B的全部方法和属性(前提是Public)
-
JAVA中的继承只有当继承,即一个儿子只能有一个父亲,父亲可有多个儿子
-
私有的东西无法被继承
-
final类不可继承
2. Object类
- JAVA中的所有类都是Object类的子类。默认继承
- JAVA中所有类都直接简介地继承了Object类。
3. Super关键字
1. 属性
public class Person {
protected String name="nihao";
}
---------------------------------------------
public class Student extends Person{
private String name="你好";
public void print(String name){
System.out.println(name);//传参
System.out.println(this.name);//该类中的name
System.out.println(super.name);//父类中的name
}
}
----------------------------------------------
public class Demo01 {
public static void main(String[] args) {
Student student = new Student();
student.print("传值");
}
}
----------------------------------------------
传值
你好
nihao
2. 方法(包含构造方法)
public class Person {
protected String name="nihao";
public Person() {
System.out.println("执行了Person的无参构造");
System.out.println("===========");
}
public void print(){
System.out.println("Person");
}
}
------------------------------------------
public class Student extends Person{
private String name="你好";
public Student() {
/*
默认调用了父类的无参构造,且必须是第一行!
隐藏代码:
super();
*/
System.out.println("执行了Student的无参构造");
System.out.println("===========");
}
public void print(){
System.out.println("Student");
}
public void test(){
print();//Student的Print方法
this.print();//Student的Print方法
super.print();//Person的Print方法
System.out.println("======");
}
}
-----------------------------------------
public class Demo01 {
public static void main(String[] args) {
Student student = new Student();
student.test();
}
}
---------------------------------------------------
执行了Person的无参构造 //默认调用了父类
===========
执行了Student的无参构造
===========
Student
Student
Person
======
3. 细节
-
super调用父类的构造方法,必须在构造方法的第一个
-
super必须只能出现在子类的方法或构造方法中
-
super和this不能同时出现在构造方法
-
this()是本类的构造,super()是父类的构造
7. 方法重写
1. 静态方法为什么不能重写
public class Person {
public static void print(){
System.out.println("Person");
}
}
--------------------------------------------
public class Student extends Person{
public static void print(){
System.out.println("Student");
}
}
-------------------------------------------------
public class Demo01 {
public static void main(String[] args) {
//方法的调用与左侧类型有关
Student student = new Student();
student.print();//调用student的print方法
//父类的引用指向子类
Person person = new Student();
person.print();//调用person的print方法
}
}
-----------------------------------
Student
Person
2. 非静态的方法
- 当去掉static后,出现了重写符,代表已经重写了父类的方法
public class Person {
public void print(){
System.out.println("Person");
}
}
--------------------------------------------
public class Student extends Person{
@Override //功能性注解,代表重写
public void print(){
System.out.println("Student");
}
}
-------------------------------------------------
public class Demo01 {
public static void main(String[] args) {
Student student = new Student();
student.print();
Person person = new Student();
person.print();
}
}
-----------------------------------
Student
Student
3. 细节
- 重写的前提是有继承关系
- 方法名,参数列表全部相同,仅方法体不同
- 修饰符:范围可扩大但不可缩小 (小private ->protected->default->public大)
- 抛出的异常:范围可缩小但不可扩大(ClassNotFoundException->Exception大)
8. 多态
1. 简介
- 同一方法根据对象不同采用多种不同的行为方式
2. 示例
public class Person {
public void print(){
System.out.println("Person");
}
}
-----------------------------------------------
public class Student extends Person{
@Override
public void print(){
System.out.println("Student");
}
//独有
public void study(){
System.out.println("学习");
}
}
----------------------------------------
public class Demo01 {
public static void main(String[] args) {
/*
一个对象的类型是确定的
如:new Student();
但是指向的引用类型不确定,且一般只能是父类引用指向子类
如:
Person s2 = new Student();
Object s3 = new Student();
person Object均为student的父类
*/
//子类能用父类的方法
Student s1 = new Student();
//父类不能调用子类独有的方法:如study()
Person s2 = new Student();
Object s3 = new Student();
/*
调用哪个方法主要看引用类型,若重写了则执行子类的方法
编译看右边,执行结果看左边引用的类型
*/
s1.print();
s2.print();
s1.study();
}
}
细节
- 多态是方法的多态,属性没有多态
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象
- 多态的动态体现在重写在执行时才能确定
- 多态是对于面向对象而言(即new出来的一个对象,同为run方法可能根据引用类型的不同而产生不同的结果,它是多态的)
9. Instanceof和类型转换
1. instanceof关键字
instanceof关键字用于判断是否存在父子关系
public static void main(String[] args) {
/*
object -> String
object -> Person -> Student
object -> Person -> Teacher
*/
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 String);
System.out.println(object instanceof Teacher);
System.out.println("===============");
Person person = new Student();
System.out.println(person instanceof Student);//ture
System.out.println(person instanceof Person);//ture
System.out.println(person instanceof Object);//ture
//System.out.println(person instanceof String);同级别,不属于父子类关系,所以编译就会报错
System.out.println(person instanceof Teacher);//flase
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 String);不属于父子类关系,所以编译就会报错
//System.out.println(student instanceof Teacher);不属于父子类关系,所以编译就会报错
-------------------------------------------
true
true
true
false
false
===============
true
true
true
false
==============
true
true
true
2. 类型转换
- 必须存在父子类关系,方便方法调用,简化代码
- 子类转父类,向上转换,会丢失一些自己独有的方法。
- 父类转子类,自动转换,向下转换。
10. static关键字&匿名代码块&静态代码块
1. static
static为静态声明,声明的变量和方法为静态变量静态方法,与类一起加载,一直占用内存,且只执行一次
private static int age = 20 ;//静态变量,可以类名引用,也可对象引用
private int score = 100;//非静态变量,只能对象引用
//静态方法
private static void run(){
System.out.println("执行一个run方法");
//go();无法引用,因为静态方法加载时,非静态方法还没加载
}
//非静态方法
private void go(){
System.out.println("执行一个go方法");
run();//可引用,因为静态方法跟类一起加载在静态方法区中
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
//System.out.println(Student.score); 非静态变量无法通过类名引用
System.out.println(s1.score);
System.out.println(s1.age);
System.out.println("=================");
s1.go();
System.out.println("===================");
Student.run();
}
----------------------------------
20
100
20
=================
执行一个go方法
执行一个run方法
===================
执行一个run方法
2. 匿名代码块
/*
一般用于赋初始值
*/
{
代码块区域
}
3. 静态代码块
/*
静态代码区因为是静态只执行一次,且一直占用内存
*/
static{
静态代码块区域
}
4. 总结
public class Student extends Person{
//代码块
{
System.out.println("输出一次代码块内容");
}
//静态代码块
static {
System.out.println("输出一次静态代码块内容");
}
//无参构造方法
public Student() {
System.out.println("输出一次构造方法的内容");
}
public static void main(String[] args) {
new Student();
System.out.println("=============");
new Student();
}
}
-----------------------------------------
输出一次静态代码块内容 //率先执行,只执行了一次
输出一次代码块内容//先于构造方法
输出一次构造方法的内容
=============
输出一次代码块内容
输出一次构造方法的内容
11. 抽象类
/*abstract 抽象类(因为是类只能单继承) :继承它的非抽象子类都必须实现它的所有抽象方法。
1. 抽象类不能new出来
2. 抽象类一定有一个以上的抽象方法
3. 抽象类有构造器
4. 抽象类存在普通的方法
*/
public abstract class Action {
//抽象方法 :方法体可以为空,是为约束
public abstract void doSomething();
public void niHao(){
System.out.println("你好");
}
}
12. 接口
1. 与类区别
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有!
- 接口:只有规范,无法实现任何方法
2. interface接口
/*
1. 接口中的所有方法都默认是Public abstract ,因此可以直接返回值+方法名
2. 类实现接口,必须实现里面的所有方法
3. 接口可以被多继承
4. 接口中定义的变量都为常量,默认 public static final
5. 接口没有构造方法,无法实例化
*/
public interface UserService {
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
public interface TimeService {
void time();
}
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 time() {
}
}
13. 内部类
1. 成员内部类
public class Outer {
private static int age=10;
public void outMethod(){
System.out.println("这是外部类的方法");
}
class Inner{
public void inMethod(){
System.out.println("这是内部类的方法");
}
//通过内部类可以调用外部类的私有属性
public void getAge(){
System.out.println(age);
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
outer.outMethod();
inner.inMethod();
inner.getAge();
}
}
--------------------------------------------
这是外部类的方法
这是内部类的方法
10
public class Outer{
}
class A{
}
2. 静态内部类
3. 局部内部类
public class Outer{
public void method(){
//局部内部类
class Inner{
public void in(){}
}
}
}
4. 匿名内部类
public class Test{
public static void main(String[] args){
//匿名内部类,没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
//匿名内部类
UserService userService = new UserService(){
@Override
public void hello(){
}
}
}
}
class Apple{
public void eat(){
System.out.println("吃")a;
}
}
interface UserService{
void hello()
}