Java知识点笔记(持续更新)

认识类和对象

0.常量用final修饰,并且要全部大写,单词间由下划线连接;

1.string类型的默认值是null;

2.int类型的默认值是0;

3.char类型的默认值是‘\u0000’;

4.boolean类型的默认值为false;

方法与重载

5.传参数的时候,基本数据类型传的是值,引用数据类型传的是指针(地址)

6.基本数据类型:加" . "不会出方法的数据类型,例如:char int double 等;

7.引用数据类型:“ . ”的出方法的,例如:数组.length,自定义的class ,接口等;

8.for()遍历数组时,可以写为:for(数据类型 标识符:数组名) eg:for(Student stu : stus);

9.this关键字:

用法1: 带参构造方法中,this指代当前的类:

               this.name=name;

               this.age=age;

              从而与传过来的参数区分开;

用法2:this 关键字可调用类里面的方法

               this.showInfo();

用法3:this关键字还可调用构造方法

               public student(int age ,string name){xxxxxx}

               现在要新增一个构造方法,加入int score 进去,可以调用之前的构造方法以减少代码量

               public student(int age,string name ,int score){

                        this(age,score);

                        this.score=score;

                }

               注:用法3的写法中,this()的调用一定要在此构造方法第一句,否则报错。

10.构造方法没有返回类型,即:写构造方法时,不加void int string之类的返回类型;

11.当自定义带参的构造方法之后,原构造方法(系统自带的)失效,如要使用,应自行重新声明

12.构造方法名与类名相同

13.方法重载:当你需要以一个函数名完成不同的功能(比如cal()函数实现两个浮点数,三个浮点数,四个浮点数相加)的情况时,可以使用方法重载,将不同功能的函数使用同一个函数名,方便后续调用;

 14.方法重载写法:public或private 以及返回值类型不影响。传参不一样(类型、数量)就可以用相同函数名。

15.成员变量(全局变量)自带初始值;

      局部变量不会自动赋初始值。

16.成员变量和局部变量可以同名,局部变量优先级更高。

封装与继承

封装

什么是封装

把类中所有的属性藏起来,把尽可能多的东西藏起来,并提供便捷的接口,避免外部直接访问类信息

如何封装

1.加private

private int health = 100 ;外部就无法访问了,仅类中可访问;

2.添加setter/getter方法

public void setHealth(int health){

        xxxxx           //判断是否超过限制

        this.health = health;

}

public int getHealth(){

        return this.health;

}

注:以set/get + 属性名为方法名是规范;

如此,用户必须通过setter和getter方法调用类属性,无法直接访问,避免了类属性的非法更改。

17.setter/getter快捷键:alt+shift+s

用途:存放两个同名的类而不冲突,类似文件夹,有助于实施访问权限的控制;

包名由小写字母组成,由小数点分开对应路径,包名前通常加入唯一前缀,通常使用组织倒置的网络域名,但包名后续部分依据不同机构内部规范而确定

包导入语句:import

为了使用不在同一个包的类,需要Java程序使用import关键字导入这个类

import 包名.类名;

eg:        import java.util.*; //导入java.util包里的所有类;

             import cn.School;//导入指定的包内指定类

18.默认使用同包内的类

19.如果想同时使用不同包的同名类,需要将类的完整限定名写全;

        eg:cn.com.oop.Dog dog = new cn.com.oop.Dog();

                cn.com.oop.pet.Dog dog2 = new cn.com.oop.pet.Dog();

20.import只会导入当前目录的所有类,不会导入当前目录子目录下的类

      eg:    import cn.com.oop.*;     不会导入cn.com.oop.pet包下的类;

21.package 放在第一句,然后是import,然后是声明类

访问权限控制

一、类的修饰:public or 什么都不写

                eg:public class Test                       or                 class Test;

相同包可以访问上述两种,但是不同包只能访问public修饰的类

public:公有访问级别

默认修饰符:包级私有访问级别

二、属性和方法的修饰

private:本类访问only

默认修饰符:同包内访问

protected :不能被其他包访问,可以被同包,子类访问

public : 都可以

static标识符

一、static成员变量 :

实例(对象)变量变为静态变量

static int name ;

可通过类名调用,或实例调用(zzy.name)(不建议)

Person.name;

注:在内存中只有一个拷贝,改变一个就改变了全部的值

二、static方法

public static void m(){}

可直接通过类名调用,也可通过实例调用(不推荐);

静态方法不能使用this和super,不能访问所属类的实例变量,实例方法,只能访问静态变量和静态方法

静态方法必须被实现

main方法是最常用的静态方法,因为它不依赖于任何类,进入类时直接被加载,成为入口

三、static代码块

静态代码块

jvm加载类时,加载静态代码块

按顺序加载多个静态块

每个静态代码块只会被执行一次

eg:

class Test        {

        static num=100;

        static {

        num+=100;   

        print num;     

}

}

        在main中:Test t1=new Test();

                           Test t2=new Test();

输出:200 200    (因为每个静态代码块只会执行一次)

继承

避免写重复的代码

将重复代码抽取到父类中

访问修饰符 class Dog extends Pet(){}

注:java中只支持单根继承,一个类只能有一个父类

继承中的修饰符使用

private 子类不能用

默认修饰符 同包内子类可以,不同包子类不行;

protected 子类可用

public 子类可用

即:子类不能继承父类的private成员和不在同一包内的默认修饰符,及构造方法;

方法重写与多态

方法重写

问题来源:子类调用父类的函数(例如:print),不能显示自己所独有的信息。

解决方法:子类重写父类方法(overriding)

构造方法不能重写,只能重写普通方法

方法:调用super ,同名方法 

/*此处有几节课断层*/

/*预留位置*/

万物始祖:object类

object类是所有类的祖先(直接或间接父亲)

object有一些方法,其中常用的方法有:

tostring:将类的信息转换为字符串返回;

equals:判断两个类是否相等;

hashcode:返回类的哈希值;

还有一个记不到了,后面再说。

重点:equals():其作用和==相等,都是判断类的一致性,返回一个布尔变量

重点2:equals的判断依据:对象在堆中的地址是否一致

复习:栈与堆:栈:存放索引  堆:存放数据 ,由栈指向堆

重写equals

在默认判断中,equals采用地址作为判断依据,并不具备普适性;

所以很多时候我们需要重写equals

MyEclipse快捷重写方法:鼠标右键找到override method ;

重写流程:

1.判断是否相等(==判断地址是否一致),如真,肯定相等;

2.判断类型是否为当前希望判断的类型(如:两个Student类):

   方法:xx(传进来的对象名) instanceof  xxx(类名),如真,代表是该类的一个实例;

3.强制类型转换:此时已经确定该对象类型,需要强制转换成当前类型(原来是obj类)从而调出当前类型私有的一些属性(obj作为父类无法调出);

4.判断需要判断的属性是否相等(name,age,money等);

tips:字符串判断相等不用“==”,原因就是上文所说,采取地址判断;

          一般判断字符串相等采用equals(),原因:equals已经在string类中被默认重写了,采取全文对比方式;

重写toString

默认的toString返回的是类名+地址,很多时候需要重写为显示需要显示的内容;

重写流程:直接改return 即可;

tips:直接输出对象,如 print(zzy)和 print( zzy.toString )是一样的,可以看成是调用了后者

          同样的,对于string来说,已经在默认中被重写了,所以直接输出和tostring输出的都是字符串内容。

 多态

设想:你要设计一个会计类,给不同职业的人发钱。怎么写?

        1. 在会计类里面用很多if else 写每个职业的薪资;

        2.在每个职业类里面写好“发钱”这一方法,会计类直接调用就好;

显然是后者。

那么问题来了,我是不是还得写很多if 来调用不同的方法呢?

No!!!!

Java虚拟机早就想到了这一点,所以对于同一父类的不同子类,只要将父类指向子类(用一个父类的指针指向子类),传参数时传父类过去,Java虚拟机就会自动调用对应的真实子类的方法;

这样的话,我们就可以只在会计类里面写一个“发钱给‘员工类’”就行了,虚拟机会自动调用相应的方法;

抽象方法与抽象类:

在上面的会计例子中,我们在员工类必须写一个空的方法:发钱,因为要给子类重写,不然无法使用多态。

其实,这种没有实现内容的方法,可以被声明为“抽象方法”,因为它只是给子类提供了一个空间。

比如上文的员工类,这个类无法被实例化:一个员工具体是什么呢?你可以实例化经理,服务员,领班,厨师。但公司里面没有一个职位叫“员工”,这种类就叫抽象类;

关于抽象类,还有几个结论/要求:

1.抽象方法没有方法体:显然,你无法给一个“员工”发工资,你只能给具体的职位发工资;

2.抽象方法存在的类一定是抽象类:如果都存在无法被实现的方法了,这个类就一定不是具体的了,只会是抽象的。;

3.抽象类不一定有抽象方法:有时我们只是认定某个类是抽象的,但是不一定马上有对应的抽象方法,可以给后面写的抽象方法留位置;

4.抽象类不能被实例化(new  类名()):显然;

5.抽象方法必须在子类中被实现,除非子类是抽象类:如果不被实现,这个抽象类就没有根基,抽象就没有抽象的源头?(此处存疑,后面学虚拟机之后应该会有更好的答案)

6.如何声明一个抽象方法/类?

              在限制符后面加abstract;

向上/向下转型(类型转换)

在前面的例子中,利用将子类由父类引用,从而利用动态绑定机制实现了多态自动匹配相应的方法,这个过程,实际上就是“向上转型”;

向上转型:子类由父类指引,从而实现多态;

向下转型:父类转为子类(常见于向上转型后,要利用子类的私有方法时,要转回来);

为什么会有这两个转型?

向上转型的问题:转型后无法访问子类原有的私有方法,比如,员工类显然无法实现打扫清洁这一属于保洁人员的方法;

此时,就需要用到向下转型,将子类转移回来,从而调用子类的方法;

语法:向上转型:父类+对象名=new 子类();

           向下转型:子类+对象名=(子类)+待转对象名;

向下转型又叫做强制类型转换:经理类一定是员工类(向上类型转换),但员工类不一定是经理类(向下类型转换)

所以,问题就出来了:从父类转移到子类的时候,有可能转错了,比如本来是经理,但是转成了服务员(你自己写的时候可能也被搞晕了,更不用说其他代码维护人员了),就会造成一个经典报错:

class cast exception ,即类型转换错误;

为了避免上述错误,一个好习惯是,每次强制类型转换的时候,用“instance of”关键字先判断一下是不是你要转的类型;

即:if a instance of  A

        //转换;

          else if a instance of B

        //转换;

直到将所有可能的子类写完,以保证转换的一定正确性。

毕竟,你不知道你的上一任给你留下了什么代码

多态的第二种常用使用方式:父类作为返回值

在上面的写法中,我们使用多态的方法是将父类代替子类传参,在参数调用时调用父类,利用Java的动态绑定机制,智能地使用一个调用写法就实现了多次的判断。

实际上,常用的多态使用方法,还可以将父类作为返回值:

还是那个员工的例子,我作为一个老板类,要找手下的员工帮我去买个东西,我找不同的员工,会买不同的东西,比如找经理买账本,找厨师买食材等等。

那么我正常的思路是:在测试类中询问要买神马,再进行Switch判断,最后将值传回老板类,由老板类进行调用不同的员工去买东西。

但是这样写,会导致测试类里面内容冗杂,本来该放到老板类处理的判断放在了测试类中。我的测试类实际上只需要最后返回的一个员工类而已;

所以我们将Switch放入老板类。

但是问题又来了:一个函数只能有一个返回类型,我们有那么多个员工类,要每个都写一个函数吗?

未免太麻烦了,也不利于后期维护。

所以我们想到了多态,我们能不能返回一个父类,利用多态的动态绑定机制,使得最后返回的这个父类(实际指向的是一个子类),能执行子类的“买东西”方法呢?

可以。我们将返回值设置为父类,在员工类(父类)中写一个abstract的买东西方法,再在子类中重写这个方法,最后在老板类中用Switch判断后new一个子类,再将一个父类指针指向这个子类。最后返回父类。

然后在测试类中,可以直接使用“父类.购物”,得益于上述的重写和动态绑定机制。

抽象类和接口

抽象类的补充:

1.为什么抽象类不能被实例化?

从语义来说,抽象类实例化毫无意义,提到猫,你会想到一只毛茸茸的球,但是提到宠物,如何将它具体化呢?

从语法来说,抽象方法没有方法体,在jvm加载之后无法执行这个方法;

2.没有抽象的构造方法:因为抽象方法没有方法体,无法执行;

3.没有抽象的静态方法:静态方法不需要实例化就能执行,但是抽象方法无方法体,无法执行;

4.抽象类可以有非抽象的构造方法,即:为子类提供的构造方法提供合适的调用。

接口:

为什么使用接口

你要写一个防盗门类。基于oop的思想,你需要写一个门类和一个锁类,但是Java只允许单根继承,那么咋办?

由防盗门继承门类,并且实现锁类的接口。

什么是接口?

从广义上说,接口是链接硬件、软件之间的物理或软件工具,在前面学习的setter和getter可以被视作一种接口,然而,在java中的接口,其实更应该看成一种特殊的类。

作为解决Java单根继承问题的工具,接口和类有着很多的相似之处;

声明:public interface MyInterface{

          //functions

}

接口有以下特点:(JDK8以前)

0.接口支持单根继承。

1.接口中的变量都是静态常量,且必须初始化 。在使用时和类一样,可以通过“接口名.常量名”使用。

2.接口中的所有方法都必须是public abstract 方法,即,接口内的方法都是没有方法体的。

3.接口不能被实例化,但可以被类实现(implement 接口名1,接口名2,接口名3......),相当于引入了多个父类,只不过此时不叫父类,叫“父接口”

4.在引入父接口之后,子类必须实现父接口的所有方法,除非子类是抽象类。

5.引入父接口之后,可以利用类似类继承中多态的写法,“接口+接口名=new 子类构造方法”,此时,接口可以作为一种数据类型来看待,可以调用与子类所共有的方法;

jdk1.8新增接口特性

1.可以有默认方法,有方法体,能被继承

可有多个默认方法;

语法:default +正常函数声明;

作用:降低了子类和接口间的耦合度;

可能遇到的问题

一、多个接口有同名default,系统不知道用哪个

解决方法1:子类中重写这个方法

解决方法2:在重写中用super指定调用哪个方法

eg:void m2(){

        MyInterface.super.m2();//指定调用MyInterface 中的m2方法;

}

二、父类和接口重名

此时默认调用父类方法,如有需要,可按上面的方法重写;

2.JDK1.8允许有静态方法,但必须是public static

由于是静态方法,不能被继承/重写,只能在接口中被调用

                                                                                                                  

     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值