Java第七章 类和对象

可将将类看做是对象的载体

1.对象:静态部分,动态部分,静态的为属性,动态的为行为。

面向对象的三大特点:

1.封装:封装变化,让封装的类或组件,尽量只负责一个领域的工作.。

2.继承:主要利用对象的共性解决同样的问题,概念形成统一,通过继承可以管理多个概念。

3.多态:同一个行为的不同表现方法 ,解决父类的方法在子类不适合的问题。

主要思想:

分而治之,高内聚,低耦合,封装变化。

主要原则:

开-闭原则:对扩展开放,对修改关闭。

类的单一指责:类定义的时候,只包含一个或者一类与类本身关系的密切功能。一个类有且只有一个改变它的原因。

面向接口编程而非面向实现:先思考做什么,为其他的组件提供什么功能。

优先使用组合而非继承:如果仅仅为了复用类,优先选择组合,如果需要复用代码的同时服用概念,使用继承。组合的耦合性比继承低。

依赖倒置:尽量依赖抽象,因为抽象是稳定的,实现是多变的。

里氏替换:子类在重写父类方法时,尽量选择扩展重写。

接口隔离:尽量定义小而精的接口,少定义大而全的接口。

迪米特法则:类与类交互时,在满足功能的基础上,传递的数据约少越好,这样可以降低耦合度。

1.构造方法:与类 同名的方法,创建类的对象时自动调用,在类中没有定义任何构造方法时,编译器会在该类中提供一个不带参数的构造方法,当类中有自定义的构造方法,则不提供,如果定义的是有参构造方法,那么调用无参构造方法会报错。这里跟C#是一样的,如果在类中定义了有参的构造函数,那么必须再定义一个无参的构造函数,否则调用无参构造函数会报错。this关键字可以调用类的成员变量和方法,this就是当前类的对象。这里还要注意下接口和抽象方法。构造方法不能有返回值,并且它可以重载。

c#语法:构造方法不会继承给子类,但是在创建子类对象时,先从子进入父,自动调用父类的构造方法,且父类构造方法先执行,子类构造方法后执行.当子类采用无参构造方法创建对象时,默认调用父类的无参构造方法,如果父类没有无参构造方法,则报编译错误(如果父类给了有参的构造函数,就不会给无参的构造函数,这时用子类的无参创建对象就会报错),解决方法有两个: 1.为父类添加无参构造方法, 2.在子类的构造方法中用base关键字指明要调用父类的哪一个有参构造方法,2优先1.多态的方式有:重写,隐藏,重载,抽象方法,接口。继承protected修饰的成员只能在派生类里调用。而java可以在同包下嗲用或者不同包下有继承关系调用。

隐藏方法:本质指的是方法用new修饰的方法,如果使用隐藏技术,调用父中的方法有2中 父类对象= new 父类()父类对象= new 子类()。如果使用隐藏技术,调用子类的方法有1中。子类 对象= new 子类()缺点:不能实现父调子!原理:两个地址,new谁在谁的方法列表中找,声明谁找谁的方法地址。

虚方法重写:用vritual关键修饰的已经实现的方法,子类中的方法名字前加 override,也可以不重写。与隐藏方法不同的是父类对象= new 子类()调子类。原理:重写方法表中地址。方法列表中有2个方法。但是原方法的地址被新方法的地址覆盖,所以new父类调用子类的方法,

抽象方法:抽象方法用abstract修饰,在子类中必须重写,除非子类中也是抽象的。重写方法用关键字override,已经重写过的方法,在子类还可以继续重写,除非被标识为sealed。sealed修饰的为封闭方法或者类。不能够被继承。封闭类(sealed修饰的类)的特点,可以new ,不能被继承。抽象类(abstract修饰的类)不能实例化,可以被继承。抽象类中可以有字段,可以有实现方法。抽象方法没有实现。抽象方法只能出现在抽象类中。放在抽象类中的抽象方法必须加abstract,实现类在实现抽象类中的抽象方法必须加Override。放在接口中的抽象方法不能加abstract,实现类在实现接口中的抽象方法不加Override。

定义使用关键字interface创建的数据类型。

接口:接口名建议用”I”开头,其后单词首字母大写。接口只关注行为,不关注数据(不能有字段),且不关注行为的实现(没有方法体),实现由实现类完成。接口是定义一组对外的行为规范,要求它的实现类必须遵循(行为默认是Public并且不能添加public,实现类必须实现接口中所有成员)父债子还也就是说子类中实现所有方法,可以有自动属性,在子类中实现。实现类中必须加public(除显示实现:方法名改为接口名加”。并且不能加任何访问修饰符,默认为private,显式实现成员只能通过接口类型的引用调用)。接口中的所有成员不能加任何访问修饰符,全部默认公有。接口中的所有成员不能有实现,全部默认抽象的。解决接口中的成员对实现类不适用的问题  如果接口中包含的方法比较多,个别不适合实现类,不适合的用显示实现,好处就是通过类的引用无法调用,【一定程度上的避免了接口污染】,解决多接口实现时的二义性。结构(struct)可以实现接口,但不能继承类

静态绑定:是指调用关系是在运行之前确定的,即编译期间 方法隐藏是静态绑定

动态绑定:是指调用关系是在运行期间确定的。运行期间,方法重写是动态绑定(运行时改地址)

-------------------------------------------------------

java语法:接口用interface关键字, 接口名以I为开头,extends 关键字用来指定继承哪个父接口。接口里可以有字段 ,但是必须初始化  接口里的字段必须为公开的、静态的、终态的(final关键字修饰也就是说是静态的),但是方法可以是私有的(Java9新特性之一)。public 等权限修饰符可以有也可以没有,没有则默认为默认权限,protected。接口只能继承接口,类只能继承类。implements 关键字用来指定该类实现了那些接口,用逗号分割多个。接口后面不能用关键字implements。一个类只能继承一个类,但是可以实现多个接口(注意这里类只能继承类不能继承接口),接口可以多继承接口并且不能继承类。这里继承时有个“@Override”,它是伪代码,表示重写(当然不写也可以),不过写上有如下好处:  1、可以当注释用,方便阅读; 2、编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错。而如果你不加@Override,则编译器将不会检测出错误,而是会认为你为子类定义了一个新方法。类不能实现类。是能实现接口。接口继承多个和接口时用“,”隔开。类实现多个接口时也用“,”隔开.继承和实现同时需要时,先写继承 再写实现 用空格 分开即可。

继承:类继承抽象类时,声明父类  new 子类 调用子类方法 , 声明子类  new 子类 调用子类方法, 抽象类不能实例化。子类不能继承父类的构造方法,但是可以用super来访问父类构造方法。java里的super关键字代替C#里的base关键字。java里的类只能继承一个类,单继承,但是可以多层继承来实现继承体系,但是可以多实现。this.(...)调用本类的构造方法,super(..)调用父类的构造方法。子类中的所有构造方法都会默认访问父类中的无参构造方法,这是因为子类继承和使用父类的数据,所以子类初始化前一定要完成父类数据的初始化,如果父类没有无参构造,子类需要显示的调用父类的有参构造方法,并且 子类的构造方法一定要访问父类的一个构造方法,这样就能初始化父类数据否则报错,并且调用要放在子类构造方法里的第一句,如果不放在第一条就可能对父类的数据进行了多次初始化。执行顺序:父类静态代码块>子类静态代码块>父类代码块>子类代码块>父类构造方法>子类构造方法。一个类的初始化过程:成员变量的初始化(静态的在最前),默认初始化,显示初始化,构造方法初始化。如果方法名一样参数不一样,根据参数的不同调用子类或者父类的方法。子类重写父类方法时,访问权限不能更低。子类重写父类方法时声明要一致,都为静态或者都为非静态。

成员变量和局部变量:成员变量可以不赋值,有默认值, 但是局部变量使用前必须赋值,没有默认值。采用就近原则。成员变量在堆中,而局部变量在栈中,因为方法执行在栈针上。 方法在内存中有一块区域 在new出对象的堆中有对应的地址索引。

关键字:public,default(什么也不加),private,protected。public可以挎包访问,defaul是在同一个包可以随意访问,private是在本类使用,即使是继承的子类也不行,protected 是和default一样的功能(同一包路径下,可以被使用),但是该权限只能修饰成员变量和成员函数。但protected允许跨包继承使用,(default不行,只能在本包下被使用)。java中默认的修饰符就是default。继承关键字:extends 接口 interface 实现关键字:implements。

类:前面只能用默认和public权限修饰符,并且外部类不能用static状态修饰符修饰。成员变量:不能用abstract 修饰。构造方法:不能用static,final,abstract修饰符。

static关键字: 被所有对象共享,随着类的加载而加载,所以优先于对象存在,所以静态的方法里不能有非静态的,只能访问静态成员变量和静态成员方法,也可被对象调用,也可以用类名调用,static修饰变量和方法在方法区里的静态区,方法区里还有class内容区域。JVM调用的main方法的参数,String 【 】args ,早期是为了接收键盘录入的数据的,格式是 java hello world。后来用Scaner代替了。

final关键字:修饰类,方法变量。final修饰的类无法被继承。final修饰的方法不能被子类重写。修饰变量,只能赋值一次,且不能再做修改,对于非静态的变量,要在构造函数完毕前赋值,但是可以在子类重写。当final修饰class等引用类型时,它的引用不能修改,但是里面的变量可以修改。对于静态的final变量,可以在static代码块中赋值或者直接赋值,不能在构造函数和非静态代码块里赋值。总结一句话:由于成员方法存在方法重写,所以它的编译看左边,运行看右边。变量和静态方法编译和运行看左边。

java中的成员访问特点:继承关系,声明父类,new子类,并且变量或者方法要有重写。在用该对象直接调用的变量或者方法的时候,变量:编译看左边,运行看左边,方法:编译看左边,运行看右边。但是要是在自己类里调用要遵循就近原则。而静态方法,编译看左边,运行看左边。静态与类有关,算不上重写。如果想要调用子类特有的方法,可以把父类强转成子类即可或者声明子类new子类即可。当子类中没有父类的方法时,声明父类new子类。调用子类没有的方法时去父类里找,如果父类里调用的是父类中的protected及以上级别的方法,那么如果子类有此方法就调用子类的,子类没有或者父类的此方法访问级别时private就调用父类的。

匿名类:调用方法,仅仅调用一次的时候。没有名字的对象,调用方法格式:new 类名().方法。匿名对象调用完毕就是垃圾,可以被垃圾回收器回收,并可以作为实际参数传递。

多态:方法的重载Overloading和重写Overriding, 这里有一个实现泛型comparable<T>接口的案例可以看一下。

抽象类:用abstract关键字修饰,抽象方法不能用private或static关键字修饰。抽象类的已经实现的方法和字段可以为私有的,也可以有常量和变量,也可以没有抽象方法。有抽象方法的类必须是抽象类,抽象类有构造方法但是不能实例化,构造函数的作用是为了让子类访问父类数据的初始化。抽象类的子类如果不想重写抽象方法,该类是一个抽象类,如果子类是一个具体的实类,那必须实现所有得抽象方法。抽象类可以new子类实例。abstract不能和private,final,static 关键字共存。抽象类可以用类名直接调用静态方法。

Java第七章 类和对象

接口:,可以多继承,多实现,方法只能抽象,只能有常量并且是静态的(接口中的变量默认为final常量合static修饰符),复制后不可修改,不能有变量。接口子类可以使抽象类,可以使具体类,具体类必须实现全部的抽象方法。接口没有构造方法,这时实现类的构造方法默认调用的是万类之祖object的无参构造函数。接口默认方法为public并且是抽象的。可以同时单继承和多实现接口,继承在先用extends,实现在后 用implements 多实现用“,”隔开。用哪个接口声明的调用就可以调用哪个接口的方法。

内部类:在一个类中再定义一个类,后者称为内部类,内部类外部类没有继承关系,分为,成员内部类、局部内部类、匿名内部类。成员内部类:内部类中可以随意使用外部类的成员方法以及成员变量(private的也可以),这里内部类一定要绑在外部类上,也就是说在外部类初始化一个内部类对象,那么内部类就会绑定在外部类上,外部类只能使用内部类的非私有的成员并且需要内部类的对象调用。若果想再外部类外面创建内部类的对象,需要先创建外部类对象 再创建 格式如下 外部类 对象 = new 外部类(), 外部类。内部类 对象名= 对象.new 内部类()或者 外部类。内部类 对象名 = new 外部类()。new 内部类(),这也说明了内部类对象依赖外部类对象。如果有内部类和外部类的成名名称相同的情况,那么内部类中的为默认为内部类的成员,用this关键字点修饰的也是内部类成员,但是用外部类。this。修饰的为外部成员,private修饰的内部类不能被外部访问,static修饰的内部类只能访问外部的静态成员,静态内部类的方法可以使静态的,也可以是非静态的。创建对象格式:外部类名。内部类名 对象名 = new 外部类()。内部类名(),调用方法 也可以写成:外部类名。内部类名。方法()。局部内部类: 就是在类的方法中定义的内部类,它的作用范围是在这个方法内,在方法的外部不能访问该内部类,但是内部类可以访问外部类的所有成员。可以在局部位置创建局部内部类对象来调用它的成员,从局部内部类访问局部变量,此变量必须为final类型,因为局部变量会随着方法调用完毕而消失(清除栈针),这个时候,内部类仍然存在,并没有立马从堆内存中消失。等待垃圾回收器回收,为了继续让数据被使用,用final修饰,这样在堆内存里存储的是一个常量值。匿名内部类:由于匿名内部类没有名称,所以匿名内部类用默认的构造方法来生成匿名内部类的对象,并会生成外部类$序号未名称的.class文件。匿名内部类的使用条件是必须继承一个类或者实现一个接口,实质就是省略了定义子类并创建子类对象再调用父类成员或重写的过程,返回一个父类声明new子类的对象。简化了代码。格式:接口 对象 = new 接口(){...};这里接口和抽象类正常是不能new对象的。静态内部类:在内部类前加static就为内部静态类。静态内部类中可以声明static成员和非静态成员,担非静态内部类中不可以声明静态成员,静态内部类不能使用外部类的非静态成员。创建静态内部类的对象不需要外部类的对象, 格式 外部类.内部类 对象 = new 类.内部类();内部类的继承:内部类可以和其他普通类一样被继承,但是继承内部类比继承普通类要复杂,需要设置专门的语法,继承时用关键字 extends  ClassA(外部类)。ClassB(内部类),在子类中必须硬性的给这个类一个有参的构造函数(classA a),并且参数为需要继承的内部类的外部类的引用,同时在构造函数中使用a。super()这样才为继承提供了必要的对象引用。并且被继承的内部类不能为静态内部类。匿名内部类用之后就等待被回收,因为栈中没有指向它的引用。

2.静态:虽然可以用对象也可以点出静态成员, 但是建议使用类名点出静态成员,否则容易造成混淆。静态方法中不可以使用关键字this,也不可以直接调用非静态方法。在方法体内的局部变量声明为静态的也是错误的。protected修饰的类或成员同包中的类可见,不同包的不可见。当不设置访问权限时默认为protected类型,也就是说只有同包的可以使用。这个与C#是有区别的,C#默认private 外部不可访问。C#的protect是只有内部或有继承的子类可以调用。 internal修饰符表示同项目。this关键字的使用其实可以省略,但是this可以作为对象作为返回值。

3. == 和equals两个比较方法是不一样的。, “”==“”运算符比较的是两个对象的引用地址是否相等,而后者比较的是两个对象引用所值的内容是否相等。所以 string a = new string (abc)  和string b = new string (abc)  a == b 结果为false a.equals(b) 为 true,类的对象调用equals代表地址是否想同。

3.1 判断对象是否相等时:对象 instanceof 类名:表示对象obj是否是class类或其子类的对象。类名.class.isInstance(对象)即对象obj能否转化为类class的对象,动态等价于instanceof。

4.对象引用超过其作用范围,这个对象被视作垃圾。将对象赋值为null。java 垃圾回收器只能回收用new操作符创建的对象,如果某些对象不是通过new操作符在内存中创建的。将不被识别。finalize()这个方法在 Object类中protected修饰的,当我们在类中定义了该方法,在垃圾回收时首先调用该方法,并且在下一次垃圾回收动作发生时,才真正的回收对象占用的内存。 但垃圾回收和此方法不保证一定会发生,如Java虚拟机面临内存损耗待尽的情形,是不会执行垃圾回收的。。finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被虚拟机宣告死亡时会先调用它finalize()方法,让此对象处理它生前的最后事情(这个对象可以趁这个时机挣脱死亡的命运),Java采用可达性分析算法来判定一个对象是否死期已到,inalize()只会在对象内存回收前被调用一次,inalize()的调用具有不确定行,只保证方法会调用,但不保证方法里的任务会被执行完(比如一个对象手脚不够利索,磨磨叽叽,还在自救的过程中,被杀死回收了)。虽然以上以对象救赎举例,但finalize()的作用往往被认为是用来做最后的资源回收。基于在自我救赎中的表现来看,此方法有很大的不确定性(不保证方法中的任务执行完)而且运行代价较高。所以用来回收资源也不会有什么好的表现。

System类:System。gc()方法为强制启动垃圾回收器,启用前会掉类中的finalize()方法,可以实现线从子类再到父类的回收。exit()方法,终止当前正在运行的java虚拟机,参数用作状态码,根据惯例,0状态表示正常终结,其他表示异常终结。currentTimeMillis(),返回与1970年1月1日午夜的时间差,单位是毫秒。arraycopy方法:从指定原数组中复制一个数组,从源数组指定位置开始复制,复制到目标数组的对应开始位置并复制规定的有效数字长度。

。cloneable 为标记类,实现此接口的类可以调用方法clone克隆一个对象。目的是为了区别于 赋值“=”, 后者地址指向同一个引用,改变一个另一个也会改变,前一个不会。

这里有很多设计模式:这个还需要自己去学习。

单例设计模式:保证此类的唯一性,类中有私有的构造方法,并提供一个静态的方法用于获得该类的实例。

制作java后缀为。class的注释文档。用Dos的javadoc命令 ,错误提示:如果提示不是内部或者外部命令(Path环境变量配置)。未指定程序包或者类,是因为lei'类的权限不够。类里的注释格式:/**  每行前用*  */,后面的格式可以是 -d 目录 -author -wersion ArrayTool.java       生成后的index.html文件就是,需要用浏览器打开,html的可以用软件转化成后缀为CHM的帮助文档。java.lang包不需要导入,其他需要导入并且注意版本是否在本地使用JDK版本之前。

代码块:在Java中使用{}括起来的代码被称为代码块,根据其位置和声明b不同可以分为局部代码块:用于限定局部变量的周期,提早释放变量,增加内存.。构造代码块:在类中的成员位置,比构造函数先执行,且每次new都会执行,可以用于把不同构造函数的相同代码重构在代码块中,对对象进行操作。静态代码块;在类的成员位置,用static修饰的{},在构造代码块前执行,并且只执行一次,是对类进行操作。静态代码块在同一个类的main方法之前执行。同步代码块:用在多线程。