面向对象语言的三大特征
封装
封装:将类中某些信息隐藏在类的内部,不允许外部类直接进行访问,而是通过该类提供的方法进行访问和操作.
封装的好处:方便修改,方便加入控制语句,隐藏类的实现细节,只能通过规定的方法访问.
具体操作:属性使用private私有权限,方法使用public公共权限.
this关键字:代表自身类的对象.使用this关键字引用成员变量,成员方法.
必须使用在非静态方法里.
常常用来区分同名的局部变量和成员变量
public class Person {
//属性 使用私有权限private 将当前属性隐藏
private String name;
private int age;
/*
为私有的属性提供专门的方法进行访问
*/
public void setName(String name){
this.name =name;
}
public String getName() {
return name;
}
public void setAge(int age){
//this 关键字 代表当前正在访问的对象
this.age=age;
}
public int getAge(){
return age;
}
}
继承
继承:
是在已有类中派生新的类,新的类拥有已有类的属性和方法,并且能够自己扩展新的方法或属性.在java中使用关键字extends表示继承关系.一个类只能有一个父类,并且子类可以调用父类所有的非私有的属性和方法.
继承的优点:
实现代码的可重用性,提高代码可扩展性.
继承的构造方法:
子类构造方法总是先调用父类构造方法,默认情况下,调用父类无参构造方法
可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法,如果用super,必须写在方法的第一句
如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法.
super关键字:
表示当前类的父类对象,在子类中可以使用super调用父类成员
方法的重写:
父类的一些方法无法满足子类的需要时,在子类可以进行重写此方法.
方法重写的规则:
方法名相同、参数列表相同;返回值类型相同;访问权限等于或大于父类权限;
注意:构造方法不能重写
举个例子,动物类(父类)
public class Animal {
private String name;
private int age;
public void eat(){
System.out.println("干饭了干饭了");
}
public Animal(){
System.out.println("animal中的无参构造方法");
}
public Animal(String name) {
System.out.println("Animal中有一个参数的构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
(狗)子类
/*
继承 使用关键字 extends
父类中存有子类的一些共有的属性和方法
子类也可以定义属于自己特有的属性和方法
*/
public class Dog extends Animal {
private String spec;//子类属性
public void jiao(){
System.out.println("汪汪汪汪汪汪");
}
public Dog(){
super("xiao");
System.out.println("Dog类中的无参构造方法");
}
public String getSpec(){
return spec;
}
public void setSpec(String spec){
this.spec=spec;
}
public static void main(String[] args) {
Dog a =new Dog();
a.setName("旺财");//父类
a.setAge(2);//父类
a.setSpec("泰迪");//子类
System.out.println(a.getName());//父类
System.out.println(a.getAge());//父类
System.out.println(a.getSpec());//子类
a.jiao();//子类
a.eat();//父类
}
}
狗的子类
public class XiaoTian extends Dog{
public void fly(){
System.out.println("飞飞飞");
}
/*
方法的重写:在父类方法无法满足或者无法实现子类方法的需求时,可以在子类中重写此方法
方法重写的要求:
方法名,参数列表相同
返回值的类型相同
访问权限大于等于父类访问权限
构造方法不能重写
super 表示当前类的父类对象
在子类中可以使用super调用父类成员
@Override 注解 理解为标签
表示此方法是从父类重写的
*/
@Override
public void eat() {
System.out.println("哮天犬吃吃吃");
super.eat();
}
/*
在调用子类构造方法时 会先调用父类构造方法 默认调用无参的构造方法
在子类构造方法的第一行可以使用super关键字调用父类的任意一个构造方法
*/
public XiaoTian(){
//super();
System.out.println("哮天犬的无参构造方法");
}
}
类之间的关系
关联关系和依赖关系
/*
关联关系的意思是一个类作为另一个类的属性存在 比如person类与phone类
has-a关系
*/
private Phone phone;//关联关系 人拥有一个手机 一对一
private Phone[] phones;//一对多的关联关系 人拥有多个手机 一对多
/*
依赖关系是在一个类中使用另一个类,可以改变另一个类中的属性等
use-a关系
*/
public void feedAnimal(Dog a){
a.setName("富贵儿");
}
抽象类
抽象类:一个类没有包含足够的信息进行描绘一个具体的对象.抽象类不能实例化对象外,其他功能依旧存在.用使用关键字abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类
特点:
抽象类不能被实例化,但可以有构造函数
继承抽象类的非抽象类必须实现其中的所有抽象方法,而已抽象类只能用作基类,表示的是一种继承关系
父类
public abstract class Animal2 {
String name;
public Animal2() {
}
/*
抽象方法
在顶层类中,一些方法的实现与子类大多不相同可以将方法声明为抽象方法
使用关键字 abstract修饰,没有方法体
*/
public abstract void eat();
public void play(){
System.out.println("想要出去玩");
}
}
//子类
/*
抽象类就相当于一个定义,然后让其他类继承
继承抽象类需要:将子类也声明为抽象类
将父类中的抽象方法进行重写
*/
public class Animal2Dog extends Animal2 {
public static void main(String[] args) {
Animal2Dog a =new Animal2Dog();
a.eat();
a.play();
}
@Override
public void eat() {
System.out.println("狗吃饭");
}
}
接口
接口:可以理解为是一个纯粹的抽象类,接口中可以定义抽象方法,使用关键字interface来定义一个接口.其作用是可以作为上层的设计需要,来进行设计功能.
接口的语法:[访问修饰符] interface 接口名称{ 声明常量;抽象方法;}
声明常量: 必须赋值,前面默认使用public static final修饰
方法: dk8以后接口中声明的抽象方法,默认是被public abstract修饰
接口的实现:使用关键字implements 实现接口,实现接口需要重写接口中的所有抽象类.
接口与接口的关系:接口可以继承接口;一个接口可以继承多个接口.
接口与类的关系:多个类可以实现一个接口;一个类可以实现多个接口,但只能继承一个类.
接口的意义:在java中一个类只能有一个父类,所以用接口可以实现多继承的逻辑
/*
接口使用关键字 interface
*/
//一个接口能够继承多个接口
public interface Animal extends InterfaceA, InterFaceB {
//声明成员变量 前面默认用 public static final 修饰
//public static final int NUM =5;
int NUM =5;
//抽象方法 默认使用public abstract修饰
//public abstract void eat();
void eat();
void sheep();
}
/*
使用关键字 implements 实现接口
一个类可以实现多个接口
一个类只能继承一个类
*/
public class Dog extends InterFaceC implements Animal, InterFaceB, InterfaceA {
//需要重写接口中的所有方法
@Override
public void eat() {
System.out.println("吃肉了");
}
@Override
public void sheep() {
System.out.printf("睡觉了");
}
@Override
public void test1() {
}
@Override
public void Test2() {
}
}
多态
多态:在同一个事物中,不同的时刻中有着不同的状态.
多态存在的必要条件:要有继承(包括接口的实现);要有方法的重写;要有父类引用指向子类对象.
多态环境中:
成员方法的调用,多态调用方式,编译时看左边,运行时看右边;
静态方法的调用,多态调用方式,编译和运行都看左边;
成员变量的调用,多态调用方式,编译和运行都看左边.
//父类
public abstract class Animal {
int num= 5;
abstract void eat() ;
abstract void sheep() ;
//静态方法
public static void testStatic(){
System.out.println("Animal 小小的测试");
}
}
//子类
public class Dog extends Animal{
int num =2;
@Override
public void eat() {
System.out.println("狗吃肉");
}
public static void testStatic(){
System.out.println("Dog 小小的测试");
}
@Override
public void sheep() {
System.out.println("睡觉觉");
}
public void play(){
System.out.println("一起玩耍");
}
}
//测试一
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
// 成员方法 多态调用方式 编译时看左边 运行时看右边
animal.eat();
//静态方法 多态调用方式 编译运行都看左边
animal.testStatic();
//成员变量 多态调用方式 编译运行都看左边
System.out.println(animal.num);
}
}
多态的应用:同一事物,在不同时刻的不同状态
public void feedAnimal(Animal animal){
animal.eat();
多态转型方式:
向上转型,默认转化方式,提高程序的扩展性
Animal dog =new Dog();//向上转行 父类类型表示所有子类 cat对象转上animal对象
向下转型:由于只能使用父类的方法,无法使用子类特定的方法,通过向下转型,可以使用子类中特有的方法.
//多态的弊端:只能使用父类中的方法 不能使用子类中特有的方法
public void feedAnimal(Animal animal){
animal.eat();
//向下转型 子类方法也可以使用
// Dog dog =(Dog)animal;
//animal instanceof Dog 在运行时检测animal中实际包含的是否是指定的类
if(animal instanceof Dog){
Dog dog =(Dog)animal;
dog.play();
}
if(animal instanceof Cat){
Cat cat =(Cat) animal;
}
}
final关键字
final用于修饰类,方法,属性和方法参数.
final的特点:
final修饰的类不能被继承;
final修饰的变量需要赋值并且不能被改变,通常再加关键字static;final修饰的变量若不直接赋值,则需要在构造方法中进行赋值;
final修饰的方法不能进行重写;
final修饰的方法参数不能进行修改.
package feifan.day1.day5;
//final修饰的类 不能被继承 public class Zi extends FinalDamo
public class FinalDamo {
//被final 修饰的变量需要赋值并且不能被改变 通常可以再加关键字 static
final static int num = 10;
// final int count;final修饰的变量如果不直接赋值 则需要在构造方法中进行赋值
/*public FinalDamo(int a){
count=a;
System.out.println(count);
}*/
//在方法参数前加入final 参数不能被修改
public void test(final int a){
// a=2;
}
//被final修饰的方法在子类中不能被重写
public final void eat(){
System.out.println("abcd");
}
public static void main(String[] args) {
/* FinalDamo f1 = new FinalDamo(2);
FinalDamo f2 = new FinalDamo(3);
f1.eat();*/
}
}