面向过程与面向对象
面向过程:
简称pop,关注于具体流程,一步步实现解决问题
面向对象:
简称oop,先设计,对现实中的事物进行分类,创建出类(在类中定义功能属性),创建出具体的对象,让对象去做具体的事情。
类
类是对现实事物的抽象。
在内存中类是存储在方法区中,而创建的对象是放在堆中,而在栈中的引用变量(及对象名)存储的是对象的地址·,在栈中通过对引用变量存储地址的调用来实现对对象的操作。
类的结构
成员变量:
类中的属性,
成员方法:
类中的功能,
构造方法:
作用是用来用来初始化新创建的对象,在创建新的对象的同时可以给构造方法里的成员变量赋值。
特点是和类的名相同,没有返回值,且不需要void修饰。
public class Car { int paice; Car(){ //无参的构造方法,每个方法都默认有,但当类中含有有参的构造方法时需自己编写 } public Car(int a){ //有参的构造方法是默认为public修饰,可以省略不写 this.paice=a; } }
代码块:
代码块: 类似一个没有名字的方法. 代码块: 实例代码块 在创建对后执行,调用构造方法之前执行,每创建一次对象,执行一次 静态代码块 在类加载时候执行,只执行一次 ,多个静态按照先后顺序
代码块在类加载时执行, 类什么时候加载?
1.main方法在哪个类中执行,这个类加载的
2.创建某个类的对象
3. 调用某个类中静态属性,方法
类加载时类中各组成部分的加载顺序:
类中的静态变量或者方法-------->类中的静态代码块(当创建具体对象是执行后面的)实例代码块---------->类里的构造方法
public class main { public static void main(String[] args) { Dome.hall();//类名调用静态方法 Dome a1=new Dome(); Dome a2=new Dome(); } static { System.out.println("你好,我是main类里的静态代码块"); //mian类里的静态代码块 } } class Dome{ static String s="Hello"; static void hall(){ System.out.println("我是Dome类里的静态方法"+s+"你好!!!"); } static { System.out.println("你好,我是Dome类里的静态代码块"); } { System.out.println("你好,我是Dome类实例代码块"); } }
由测试结果可以看出,类的静态代码块在类加载时只会执行一次,而实例代码块每创建一个实例(对象)就会执行一次。
注意:实例代码块比类的构造方法更先执行!!!!!
包:
●包的概念:
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
包的作用:
避免类重名
按照不同功能管理类
控制访问权限
访问权限修饰符:
Java语言有四个权限访问修饰符,权限从大到小依次为:
1)public :公共权限 修饰类、属性、方法。可以被任意类访问
2)protected:受保护的权限 修饰属性、方法。
可以被同包类访问,如果不是同包类,必须是该类的子类才可以访问。
3)default:同包权限 修饰类、属性、方法。只能被同包的类访问
4)private:私有权限 修饰属性、方法。 只能在本类中访问
具体应用
一个包导入了另一个包,在该包中创建了另一个包其中类的一对象,那么在该包便中便可以调用导入包中该类的public修饰的成员变量或者是方法
3.面向对象语言--封装 继承 多态
封装:private
使用各种访问权限修饰符,对类中的信息进行隐藏,向向外提供一个访问的方法,便于控制
例如: 成员变量私有化 单例模式 构造方法私有化
public class main { public static void main(String[] args) { Dome a1=Dome.establish(); //静态方法生成对象 Dome a2=Dome.establish(); System.out.println(a1); System.out.println(a2); } }/*单例模式在程序中只能生成一个对象。 使用方法:1.将构造方法私有化,防止在类外可以调用构造方法生成新的类 2.设置一个方法来控制对象的生成 */ class Dome{ private static Dome one; private Dome(){ } public static Dome establish(){ if(one==null){ //防止每次调用生成新的对象 one=new Dome(); } return one; } }
在类中自己定义方法来访问或者改变私有化部分的内容
继承:extends
继承:继承是面向对象程序设计不可缺少的设计思想,是实现代码可重
用的根基,是提高代码可扩展性的主要途径。
● 继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,
并能扩展新的能力。
● 在JAVA中使用extends关键字来表示继承关系。
● JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个
直接父类。
● 继承之后子类可以调用父类的所有非私有属性和非私有方法
● 何时使用继承?
● 继承与真实世界类似
● 只要说“猫是动物”
● 狗也是动物
符合is-a关系的设计,使用继承
将子类共有的属性和行为放到父类中
● 继承是代码重用的一种方式
继承中的构造方法:
在创建子类对象的时候,会先调用父类构造方法创建父类然后在调用子类构造方法创建子类对象;
在创建子类对象时,构造方法按照继承顺序依次从上向下调用;
在子类的构造方法中,第一行都有默认的supper();来调用父类的无参构造方法,当然亦可以用supper(参数列表);
来调用父类的有参构造方法.若要使用supper(参数列表);要放在子类构造方法的第一行,
public class Galaxy/*银河系*/ { //父类 private String Gname; Galaxy(String Gname){ this.Gname=Gname; System.out.println("银河系"); } void pr(){ System.out.println(Gname); } public static void main(String[] args){ solarsystem on=new solarsystem("太阳","地球"); //子类含参构造方法 on.pr(); //对象名调用父类中的pr();方法 on.prn(); //对象名调用子类中的prn();方法 }} class solarsystem extends Galaxy/*太阳系*/{ //子类 private String sname; solarsystem(String Gname,String sname) { super(Gname); //将Gname通过super传给父类的构造方法 this.sname=sname; System.out.println("太阳系"); } void prn(){ System.out.println(sname); super.pr(); //在子类方法中通过super来调用父类中的方法 } }
● 方法的重写(OverRide)
● 应用场景
当父类的方法实现不能满足子类需求时,可以对方法进行重写( override)
● 在子类中可以根据需要对从基类中继承来的方法进行重写。
● 方法重写规则
• 方法名相同、参数列表相同;
• 返回值类型相同;
• 访问权限不能小于父类权限;
注意:构造方法,静态方法不能重写,成员变量不存在重写
抽象类:
● 抽象方法
• 抽象方法是一种特殊的方法:它只有声明,而没有具体的实现
抽象方法必须用abstract关键字进行修饰
/*抽象类是由abstract修饰的类,其中可以含有抽象方法也可以不含,其中也可以含有非抽象类,一旦继承即必须重写实现所有的抽象类方法,否则继承类也为抽象类*/ public abstract class Person{ String name; /*在一些靠顶层的类,它的实现与子类大多数不同,没必要在顶层类实现,声明功能即可 abstract 修饰的方法是抽象方法,没有方法体 */ public abstract void speak(); }
①子类在继承抽象类后,需要将父类中的所有抽象方法重写完成;
②抽象类和抽象方法需要用abstract修饰,一般类不能使用;
③抽象类不一定是最顶层的类,但一定不是最底层的类;
④抽象类有构造函数,但不能创建对象,抽象类的构造函数是为了给成员变量初始化的;
⑤抽象类也可以继承其他的类;
⑥(对于抽象类中的抽象方法的修饰符)abstract关键字不能和private关键字、static关键字、final关键字共存,private导致子类无法重写父类的抽象函数,static导致抽象函数可以通过类名直接调用,而抽象函数是没有方法体的,因此调用抽象函数没有意义,final表示“最终的”,它修饰的函数子类是无法重写的。
public abstract class Vehicle { public abstract String NoOfWheels(); public String No(){ System.out.println("抽象类的非抽象方法"); return "抽象类的非抽象方法"; } }
多态
同一种事物,在不同时刻表现不同的状态
多态存在的三个必要条件
● 要有继承(包括接口的实现)(前提条件)
● 要有重写(前提条件)
● 父类引用指向子类对象
Animal是父类名,dog是继承Animal的子类名
Animal a=new dog;
a. 是编译期,调用Animal类中的方法,而a.eat();是运行期间,调用的是重写后的方法;
多态的向上转型 (自动转型)
Father类 对象名=new Son类;
可以调用父类成员,调用重写的父类方法(原因是因为该引用变量是父类的,在编译期间,只能调用该引用类型中特有的方法),但无法调用子类特有的方法和子类的成员变量
对于成员: 1.编译看左边,运行看左边 对于方法:2.编译看左边,运行看右边 对于静态方法:3.编译看左边,运行看左边
特点:无法调用子类特有的成员方法,子类的成员变量
优缺点: 父类引用表示子类对象,提升程序的扩展性 缺点: 父类类不能调用 子类中特有的方法
多态的向下转型 (强制转型)
new 子2=(Son类)对象名;
父类引用 instanceof 具体的子类类型
instanceof 判断父类引用实际表示的对象 是不是 指定类型
特点:向下转型后便可以调用子类
接口
接口类似于抽象类( 可以看做是一个更彻底的抽象类 )
接口和抽象类 都是用于在顶层类,指定规范(设计功能).
• 接口存在的意义:
java中一个类只能有一个父类,所以用接口可以实现多继
承的逻辑 。
• 从本质上讲,接口是一种特殊的抽象类,这种抽象类中包含抽象方法。
package com.ffyc.javaoop.day6.demo2; public class Test { public static void main(String[] args) { /* 接口名只能调用接口中静态的成员 */ //System.out.println(Animal.num); //Animal.testStatic(); Animal dog = new Dog(); Animal cat = new Cat(); } public void feedAnimal(Animal animal){ animal.eat(); } }
package com.ffyc.javaoop.day6.demo2; /* 设计动物接口 jdk8之前 接口只能定义 静态常量 和 抽象方法 jdk8之后 接口增加了静态方法 默认方法 interface 修饰的是接口 接口中没有构造方法 不能创建对象 接口也表示抽象(功能设计),也是需要其他类来实现的(继承) 一个接口 可以 继承多个接口 一个类可以实现多个接口 一个类只能直接继承一个类 */ public interface Animal extends Fly,InterFaceA{ //public static final int num = 10; int num = 10; //接口中的成员变量默认是 静态常量 //public abstract void eat(); void eat(); //接口定义抽象方法 //静态方法 直接通过接口名调用 public static void testStatic(){ System.out.println("testStatic"); } //默认 通过子类对象调用 public default void testDefault(){ System.out.println("testDefault"); } }
接口的特性
• 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字
• 接口中方法可以是抽象的,静态的,默认的
• 接口中声明的属性默认为 public static final 的
• 接口不是被类继承了,而是要被类实现
• 接口不能实例化对象,无构造方法
• 一个类可以实现多个接口
• 与继承关系类似,接口与实现类之间存在多态性
• 一个接口能继承其它多个接口
• 当类实现接口的时候,类要实现接口中所有的抽象方法。否则,类必须
声明为抽象的类