Java--三大特性--封装、继承和多态

封装

1 概述
封装是指隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式。

好处:

1、 提高安全性

2、 提高重用性

1.2 private关键字
是一个权限修饰符,用于修饰成员变量和成员函数,被私有化的成员只能在本类中访问。

想要修改只能,对外提供公共的,get和set方法。

1.3 demo1:封装学生

public class Student {

//String name;

       //把属性隐藏起来

       private String name;

       //提供公共的访问方法

       //设置公共的赋值方法

       public void setName(String n){

              name=n;

       }
     
       //设置公共的取值方法

       public String getName(){
              return name;
       }     

       int age;

}
 
class StDemo{

       public static void main(String[] args) {

              Student s = new Student();

              //不能访问私有的

              //s.name="zhangsan";

              //System.out.println(s.name);s

              //利用setXxx()给属性赋值

              s.setName("zhangsan");

              //利用getXxx()给属性取值

              System.out.println(s.getName());

       }

}

1.4 创建对象的流程
Person p = new Person();//短短这行代码发生了很多事情

  1.  把Person.class文件加载进内存
    
  2.  在栈内存中,开辟空间,存放变量p
    
  3.  在堆内存中,开辟空间,存放Person对象
    
  4.  对成员变量进行默认的初始化
    
  5.  对成员变量进行显示初始化
    
  6.  执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
    
  7.  堆内存完成
    
  8.  把堆内存的地址值赋值给变量p ,p就是一个引用变量,引用了Person对象的地址值
    

1.5 匿名对象
没有名字的对象,是对象的简化表示形式。

使用场景:

1、 当被调用的对象只调用一次时(多次会创建多个对象浪费内存)

Demo d = new Demo();

d.sleep();

d.game();

//这个d就是对象的名字。

也可以写成:

new Demo().show();//创建了一个对象调方法

new Demo().game();//又创建了一个对象调方法

2. 继承

2.1 概念
继承是面向对象最显著的一个特性。

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类/超类/基类。

这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。

提高复用性:只要继承父类,就能有一样的功能

class A extends c{  //原来的eat()拿走了   }

class B extends c{  //原来的eat()拿走了  }

class c{

    public void eat(){

       syso("eat");

    }

}

2.2 特点

1、 使用extends关键字

2、 相当于子类把父类的功能复制了一份

3、 java只支持单继承

4、 继承可以传递(爷爷,儿子,孙子的关系)

5、 不能继承父类的私有成员

6、 继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展

7、 像是is a 的关系

2.3 入门案例

public class TTT {

       public static void main(String[] args) {

              Zi zi = new Zi();

              zi.speak();

              System.out.println(zi.skin);

              System.out.println(zi.addr);
       }

}
 

class Fu{

       String skin="黄种人";

       String addr="大成都";     
       public void speak(){

              System.out.println("Fu...speak()");
       }
}

//通过extends和父类发生继承关系

//所有父类的功能,子类都可以继承过来,注意不能是private的

class Zi extends Fu{

       //什么都不写,能不能把父亲的内容复制一份出来

}

2.4 super关键字

1、 通过super关键字可以使用父类的内容

2、 super代表父类的一个引用对象

3、 如果用,必须出现在调用位置的第一行

2.5 方法的重写

1、 继承后,子类就拥有了父类的功能

2、 那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能

3、 子类中方法签名与父类完全一样(包括方法的返回值,方法名和参数列表,完全一致)时,会发生覆盖/复写操作,相当于修改功能

注意:

1、父类中的私有方法不能被重写

2、子类重写父类方法时,修饰符要大于等于父类修饰符的权限

2.6 继承中的用法
2.6.1 成员变量的使用
局部的,成员的,父类的。

public class Test2_LeiVariable {                         

       public static void main(String[] args) {

              Sub2 s= new Sub2();

              s.show();
       }

}

class Fu2{

       int num=20;

}
 
class Sub2 extends Fu2{

       int num;

       public void show(){

              int num=9;

              System.out.println(num);//变量的就近原则

       System.out.println(this.num);//调用本类的成员变量,相当于Sub2.num

              System.out.println(super.num);//调用父类的成员变量
       }
}

2.6.2 成员方法的使用
继承方法,特有方法,重写方法

p

ublic class Test3_LeiMethod {

       public static void main(String[] args) {

              Sub3 s=new Sub3();

              s.testShow();//调用普通方法,

s.eat();//调用重写方法,子类已经重写了父类的方法,从此再用,就是儿子的实现方式

       }

}

class Fu3{

       public void show(){

              System.out.println("Fu...show()");
       }
      
       public void eat(){
              System.out.println("爸爸吃肉");
       }
}

class Sub3 extends Fu3{

       //普通方法

       public void testShow(){

              super.show();//调用父类的eat()

       }
      
       //重写方法

       //方法签名完全一致的情况就是发生了重写

       public void eat(){

              System.out.println("儿子吃肉");
       }
      
}

2.6.3 构造方法的使用

1、 子类创建对象时,默认会去访问父类的无参构造方法

2、 在构造方法的第一行,都有一条默认的语句:super();

3、 父类没有无参构造时,可以用super调用父类的其他构造

public class Test4_LeiConstruct {

       public static void main(String[] args) {

Sub4 s = new Sub4();//创建子类对象,在调用子类无参构造前,会先去调用父类的无参构造

       }

}
 
class Fu4{

       public Fu4(){

              System.out.println("Fu4.Fu4()");

       }      
       public Fu4(String name){

              System.out.println("Fu.."+name);
       }

}
 
class Sub4 extends Fu4{

       public Sub4(){

//           super();//默认就存在的,而且在第一行

              super("zhangsan");//调用父类中含参的构造方法

              System.out.println("Sub4.Sub4()");
       }
             public Sub4(String name){

              this();//调用本类的无参构造

              System.out.println("Sub.."+name);

       }

}

2.7 拓展
2.7.1 this和super的区别

1、 this代表本类对象的引用,super代表父类对象的引用。

2、 this用于区分局部变量和成员变量

3、 super用于区分本类变量和父类变量

4、 this.成员变量 this.成员方法() this(【参数】)代表调用本类内容

5、 super.成员变量 super.成员方法() super(【参数】),代表调用父类内容

6、 this和super不可以同时出现在同一个构造方法里,他们两个只要出现都得放在第一行,同时出现的话,到底第一行放谁呢。。

2.7.2 重写与重载的区别(Overload和Override的区别)

1、重载:是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同

2、重写:是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型

3、重写是父类与子类之间多态性的一种表现

4、重载是一类中多态性的一种表现

2.8.3 继承的内存结构
在这里插入图片描述

3 多态

3.1 概念

多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。

主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。

好处是可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。

例如:水,在不同时刻可以有多种形态,包括水蒸气,冰,水。

Java怎么体现多态呢?狗有两种形态:狗和小动物

class Animal

class Dog extends Animal

Dog d = new Dog();//狗是狗

Animal a=new Dog();//狗是小动物,创建了狗的对象,赋值给动物对象,这就是多态

3.2 特点

1、 多态的前提是继承

2、 要有方法的重写

3、 父类引用指向子类对象,如:Animal a = new Dog(); – 小到大,向上转型

4、 多态中,编译看左边,运行看右边

3.3 入门案例

public class p {

       public static void main(String[] args) {

              /*Animal  a = new Animal();
              a.eat();
             
              Dog d = new Dog();

              d.kanjia();

              d.eat();*/
             

//父类引用指向子类对象--把右面的小的,给了左面大的。相当于从小到大的过程,向上造型。

              Animal an = new Dog();

              an.eat();//只可以用父类的功能,这就统一了调用的标准

              //狗吃肉,由于eat()发生了重写,所以父类方法被覆盖掉了
       }

}

class Animal{
       public void eat(){
              System.out.println("大小通吃");
       }
}

class Dog extends Animal{
       public void kanjia(){
              System.out.println("狗可以看家");
       }     
       public void eat(){
              System.out.println("狗吃肉");
       }
}

3.4 多态的好处

1、 多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法。

2、 提高了程序的扩展性和可维护性

public class Q {
      public static void main(String[] args) {
              //多态--父类引用指向子类对象
              Dog a2=new Dog();
              Cat a2 = new Cat();
              Animal2 a2 = new Dog();
              eat(a2);//传入的参数满足条件就可以,运行右面的功能
       }      
//封装共性方法,不关心具体类型,只要传入的参数是子类就可以
       public static void eat(Animal2 a){
              a.eat();
       }
}

3.5 多态的使用
3.5.1 特点

1、成员变量:使用的是父类的

2、成员方法:由于存在重写现象所以使用的是子类的

3、静态成员:随着对象而存在,谁调用的就返回谁的

3.5.2 测试

public class K {

       public static void main(String[] args) {
              Fu2 f = new Zi2();//多态,只能用父类的。。。
              //多态的成员变量,就是父类的
              System.out.println(f.num);//10           
              //成员方法,因为存在重写,所以是子类的
              f.study();//Zi..study()
              //静态成员,谁调用就是谁的
              System.out.println(f.count);//10
              f.sleep();//Fu..sleep()
       }
}

 
class Fu2{

       int num=10;

       static int count=10;

       public void study(){

              System.out.println("Fu..study()");
       }     
       public static void sleep(){
              System.out.println("Fu..sleep()");
       }
}
 
class Zi2 extends Fu2{

       int num=20;

       static int count=20;

       public void study(){
              System.out.println("Zi..study()");
       }    
       public static void sleep(){

              System.out.println("Zi..sleep()");

       }

}

3.6 拓展

3.6.1 静态代码块,构造代码块,局部代码块 !!!执行顺序:静态代码块—构造代码块—构造函数

1、 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化

2、 构造代码块:在创建对象时会自动调用,每次创建对象都会被调用

3、 局部代码块:方法里的代码块

public class haha {
       public static void main(String[] args) {

              //必须创建对象,不然静态代码块咋随着类的加载而加载。。

              Block m =  new Block();//静态1  静态2  构造1  构造2  局部1

              System.out.println();

              Block m2 =  new Block();//构造1  构造2  局部1,说明静态代码只被执行一次就是在类第一次初始化时
       }
}
class Block{
       {
              System.out.println("构造1");
       }
       static{
              System.out.println("静态1");
       }

       public Block(){
              {
                     System.out.println("局部1");
              }

       }

       {
              System.out.println("构造2");
       }
       static{
              System.out.println("静态2");
       }

     
}

3.7.2 静态变量和实例变量的区别

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。

在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

3.7.3 向上转型和向下转型

在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。

在应用中就存在着两种转型方式,分别是:向上转型和向下转型。

比如:父类Parent,子类Child

向上转型:父类的引用指向子类对象Parent p=new Child();

说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。

向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。

Parent p = new Child();//向上转型,此时,p是Parent类型

Child c = (Child)p;//此时,把Parent类型的p转成小类型Child

//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的

说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值