Java学习基础篇(9)

1、程序在什么情况下会出现空指针异常呢?
    空引用 访问 "对象相关"的数据时,会出现空指针异常。
    垃圾回收器主要针对堆内存。

2、方法在调用的时候参数是如何传递的?
    实际上,在java语言中,方法调用时参数传递,和类型无关,都是将变量中保存
    的那个“值”传过去,这个“值”可能是一个数字100,也可能是一个java对象的内存
    地址:0x1234
        记住这句话:不管是哪一种数据类型的传递,都是将“变量中保存的那个值复制一份传递过去。”

3、构造方法。
    3.1、当一个类中没有提供任何构造方法,系统默认提供一个无参数的构造方法。
    这个无参数的构造方法叫做缺省构造器。

   3.2、当一个类中手动的提供了构造方法,那么系统将不再默认提供无参数构造方法。
    建议将无参数构造方法手动的写出来,这样一定不会出问题。

   3.3、无参数构造方法和有参数的构造方法都可以调用。
        Student x = new Student();
        Student y = new Student(123);
    
    3.4、构造方法支持方法重载吗?
        构造方法是支持方法重载的。
        在一个类当中构造方法可以有多个。
        并且所有的构造方法名字都是一样的。

        方法重载特点:
            在同一个类中,方法名相同,参数列表不同。

   3.5、对于实例变量来说,只要你在构造方法中没有手动给它赋值,
    统一都会默认赋值。默认赋系统值。

    构造方法需要掌握的知识点:
        1.构造方法有什么作用?
        2.构造方法怎么定义,语法是什么?
        3.构造方法怎么调用,使用哪个运算符?
        4.什么是缺省构造器?
        5.怎么防止缺省构造器丢失?
        6.实例变量在类加载是初始化吗?实例变量在什么时候初始化?

4、封装

    4.1、面向对象的三大特征:
        封装
        继承
        多态

        有了封装,才有继承,有了继承,才能说多态。
    
    4.2、面向对象的首要特征:封装 。什么是封装?有什么用?
        现实生活中有很多现实的例子都是封装的,例如:
            手机,电视机,笔记本电脑,照相机,这些都是外部有一个坚硬的壳儿。
            封装起来,保护内部的部件。保证内部的部件是安全的。另外封装了之后,
            对于我们使用者来说,我们是看不见内部的复杂结构的,我们也不需要关心
            内部有多么复杂,我们只需要操作外部壳儿上的几个按钮就可以完成操作。

        那么封装,你觉得有什么用呢?
            封装的作用有两个:
                第一个作用:保证内部结构的安全。
                第二个作用:屏蔽复杂,暴露简单。
            
        在代码级别上,封装有什么用?
            一个类体当中的数据,假设封装之后,对于代码的调用人员来说,
            不需要关心代码的复杂实现,只需要通过一个简单的入口就可以访问了。
            另外,类体中安全级别较高的数据封装起来,外部人员不能随意访问,
            来保证数据的安全性。
        
    4.3、怎么进行封装,代码怎么实现?
        第一步:属性私有化(使用private关键字进行修饰。)
        第二步:对外提供简单的操作入口。

5、封装的代码实现两步:

    第一步:属性私有化

    第二步:1个属性对外提供两个set和get方法。外部程序只能通过set方法修改,只能通过get方法读取,
    可以在set方法中设立关卡来保证数据的安全性。

    在强调一下:
        set和get方法都是实例方法,不能带static。
        不带static的方法称为实例方法,实例方法的调用必须先new对象。

        set和get方法写的时候有严格的规范要求:(大家要按照规矩来)
            set方法长这个样子:
                public void set+属性名首字母大写(1个参数){
                    xxx = 1个参数;
                }
            get方法长这个样子:
                public 返回值类型 get+属性名首字母大写(无参){
                    return xxx;
                }

6、static关键字
    2.1、static修饰的统一都是静态的,都是类相关的,不需要new对象。直接采用“类名.”访问。
    2.2、当一个属性是类级别的属性,所有对象的这个属性的值是一样的,建议定义为静态变量。

7、this
    7.1、this是一个关键字,是一个引用,保存内存地址指向自身。
    7.2、this可以使用在实例方法中,也可以使用在构造方法中。
    7.3、this出现在实例方法中其实代表的是当前对象。
    7.4、this不能使用在静态方法中。
    7.5、this. 大部分情况下可以省略,但是用来区分局部变量和实例变量的时候不能省略。
    7.6、this() 这种语法只能出现在构造方法第一行,表示当前构造方法调用本类其他的
    构造方法,目的是代码复用。

8、继承extends
    8.1、什么是继承,有什么用?
        继承:在现实世界当中也是存在的,例如:父亲很有钱,儿子不用努力也很有钱。
        继承的作用:
            基本作用:子类继承父类,代码可以得到复用。(这个不是重要的作用,是基本作用。)
            主要(重要)作用:因为有了继承关系,才有了后期的方法覆盖和多态机制。
    
    8.2、继承的相关特性
        ① B类继承A类,则称A类为超类(superclass)、父类、基类,
        B类则称为子类(subclass)、派生类、扩展类。
            class A{}
            class B extends A{}
            我们平时聊天说的比较多的是:父类和子类。
            superclass 父类
            subclass 子类

        ② java 中的继承只支持单继承,不支持多继承,C++中支持多继承,
        这也是 java 体现简单性的一点,换句话说,java 中不允许这样写代码:
            class B extends A,C{ } 这是错误的。

        ③ 虽然 java 中不支持多继承,但有的时候会产生间接继承的效果,
        例如:class C extends B,class B extends A,也就是说,C 直接继承 B,
        其实 C 还间接继承 A。

        ④ java 中规定,子类继承父类,除构造方法不能继承之外,剩下都可以继承。
        但是私有的属性无法在子类中直接访问。(父类中private修饰的不能在子类中
        直接访问。可以通过间接的手段来访问。)

        ⑤ java 中的类没有显示的继承任何类,则默认继承 Object类,Object类是 
        java 语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有 
        Object类型中所有的特征。

        ⑥ 继承也存在一些缺点,例如:CreditAccount 类继承 Account 类会导致它
        们之间的耦合度非常高,Account 类发生改变之后会马上影响到 CreditAccount 类

10、继承extends
    
    10.1、测试:子类继承父类之后,能使用子类对象调用父类方法吗?
        可以,因为子类继承了父类之后,这个方法就属于子类了。
        当然可以使用子类对象来调用。

    10.2、在实际开发中,满足什么条件的时候,我可以使用继承呢?
        凡是采用“is a”能描述的,都可以继承。
        例如:
            Cat is a Animal:猫是一个动物
            Dog is a Animal:狗是一个动物
            CreditAccount is a Account:信用卡账户是一个银行账户
            ....
        
        假设以后的开发中有一个A类,有一个B类,A类和B类确实也有重复的代码,
        那么他们两个之间就可以继承吗?不一定,还是要看一看它们之间是否能够
        使用is a来描述。

            class Customer{
                String name; // 名字
                // setter and getter
            }

            class Product{
                String name; // 名字
                // setter and getter
            }

            class Product extends Customer{
            
            }

            以上的继承就属于很失败的。因为:Product is a Customer,是有违伦理的。

    10.3、任何一个类,没有显示继承任何类,默认继承Object,那么Object类当中有
    哪些方法呢?老祖宗为我们提供了哪些方法?

        以后慢慢的大家一定要适应看JDK的源代码(多看看牛人写的程序自己才会变成牛人。)
        先模仿后超越。
        java为什么比较好学呢?
            是因为Java内置了一套庞大的类库,程序员不需要从0开始写代码,程序员可以
            基于这套庞大的类库进行“二次”开发。(开发速度较快,因为JDK内置的这套库
            实现了很多基础的功能。)

            例如:String是SUN编写的字符串类、System是SUN编写的系统类。
            这些类都可以拿来直接使用。
        
        JDK源代码在什么位置?
            C:\Program Files\Java\jdk-13.0.2\lib\src.zip
        
        你现在能看懂以下代码了吗?
            System.out.println("Hello World!");
            System.out 中,out后面没有小括号,说明out是变量名。
            另外System是一个类名,直接使用类名System.out,说明out是一个静态变量。
            System.out 返回一个对象,然后采用“对象.”的方式访问println()方法。
        
        我们研究了一下Object类当中有很多方法,大部分看不懂,其中有一个叫做toString()
        的,我们进行了测试,发现:
            System.out.println(引用);
            当直接输出一个“引用”的时候,println()方法会先自动调用“引用.toString()”,然后
            输出toString()方法的执行结果。
        
11、方法覆盖
    
    11.1、什么时候考虑使用方法覆盖?
        父类中的方法无法满足子类的业务需求,子类有必要对继承过来的方法进行覆盖。

    11.2、什么条件满足的时候构成方法覆盖?
        第一:有继承关系的两个类
        第二:具有相同方法名、返回值类型、形式参数列表
        第三:访问权限不能更低。
        第四:抛出异常不能更多。

    11.3、关于Object类中toString()方法的覆盖?
        toString()方法存在的作用就是:将java对象转换成字符串形式。
        大多数的java类toString()方法都是需要覆盖的。因为Object类中提供的toString()
        方法输出的是一个java对象的内存地址。

        至于toString()方法具体怎么进行覆盖?
            格式可以自己定义,或者听需求的。(听项目要求的。)

    11.4、方法重载和方法覆盖有什么区别?

        方法重载发生在同一个类当中。

        方法覆盖是发生在具有继承关系的父子类之间。

        方法重载是一个类中,方法名相同,参数列表不同。

        方法覆盖是具有继承关系的父子类,并且重写之后的方法必须和之前的方法一致:
            方法名一致、参数列表一致、返回值类型一致。

12、多态的基础语法
    
    12.1、向上转型和向下转型的概念。

        向上转型:子--->父 (upcasting)
            又被称为自动类型转换:Animal a = new Cat();

        向下转型:父--->子 (downcasting)
            又被称为强制类型转换:Cat c = (Cat)a; 需要添加强制类型转换符。
            什么时候需要向下转型?
                需要调用或者执行子类对象中特有的方法。
                必须进行向下转型,才可以调用。
            向下转型有风险吗?
                容易出现ClassCastException(类型转换异常)
            怎么避免这个风险?
                instanceof运算符,可以在程序运行阶段动态的判断某个引用指向的对象
                是否为某一种类型。
                养成好习惯,向下转型之前一定要使用instanceof运算符进行判断。
        
        不管是向上转型还是向下转型,首先他们之间必须有继承关系,这样编译器就不会报错。

    12.2、什么是多态。
        多种形态,多种状态,编译和运行有两个不同的状态。
        编译期叫做静态绑定。
        运行期叫做动态绑定。
        Animal a = new Cat();
        // 编译的时候编译器发现a的类型是Animal,所以编译器会去Animal类中找move()方法
        // 找到了,绑定,编译通过。但是运行的时候和底层堆内存当中的实际对象有关
        // 真正执行的时候会自动调用“堆内存中真实对象”的相关方法。
        a.move();

        多态的典型代码:父类型的引用指向子类型的对象。(java中允许这样写代码!!!)

    

13、多态在开发中有什么作用?
    非常重要:五颗星。。。。(多态你会天天用,到处用!!!!)

    多态在开发中的作用是:
        降低程序的耦合度,提高程序的扩展力。

        public class Master{
            public void feed(Dog d){}
            public void feed(Cat c){}
        }
        以上的代码中表示:Master和Dog以及Cat的关系很紧密(耦合度高)。导致扩展力很差。

        public class Master{
            public void feed(Pet pet){
                pet.eat();
            }
        }
        以上的代表中表示:Master和Dog以及Cat的关系就脱离了,Master关注的是Pet类。
        这样Master和Dog以及Cat的耦合度就降低了,提高了软件的扩展性。
    
    面向对象的三大特征:
        封装、继承、多态

        真的是一环扣一环。

        有了封装,有了这种整体的概念之后。
        对象和对象之间产生了继承。
        有了继承之后,才有了方法的覆盖和多态。
    
    这里提到了一个软件开发原则:
        七大原则最基本的原则:OCP(对扩展开放,对修改关闭)
        目的是:降低程序耦合度,提高程序扩展力。
        面向抽象编程,不建议面向具体编程。

14、解释一些前面无法解决的问题

    私有方法无法覆盖。

    方法覆盖只是针对于“实例方法”,“静态方法覆盖”没有意义。(这是因为方法覆盖通常和多态联合起来)

    总结两句话:
        私有不能覆盖。
        静态不谈覆盖。

    在方法覆盖中,关于方法的返回值类型。
        什么条件满足之后,会构成方法的覆盖呢?
            1、发生具有继承关系的两个类之间。
            2、父类中的方法和子类重写之后的方法:
                具有相同的方法名、相同的形式参数列表、相同的返回值类型。
        
        学习了多态机制之后:
            “相同的返回值类型”可以修改一下吗?
                对于返回值类型是基本数据类型来说,必须一致。
                对于返回值类型是引用数据类型来说,重写之后返回值类型可以变的更小(但意义不大,实际开发中没人这样写。)。

15、super关键字

    super能出现在实例方法和构造方法中。

    super的语法是:“super.”、“super()”

    super不能使用在静态方法中。

    super. 大部分情况下是可以省略的。

    super.什么时候不能省略呢?
        父类和子类中有同名属性,或者说有同样的方法,
        想在子类中访问父类的,super. 不能省略。

    super() 只能出现在构造方法第一行,通过当前的构造方法去调用“父类”中
    的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。

    super的使用:
        super.属性名                【访问父类的属性】
        super.方法名(实参)        【访问父类的方法】
        super(实参)                    【调用父类的构造方法】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值