说来也羞愧,回首过去的这半年,我是真的不知道自己干了什么,唉,最近用了几天的 时间把疯狂JAVA讲义看了一遍,写下一点点感悟,没什么其他意思,就是想祭奠一下挥霍的时光…
JAVA语言概述
这个其实真的没什么可说的,不过我还是想简单写点,一开始我是真的反感JAVA的繁琐,从最简单的类,一直到捋不清的多态继承关系,相比之下我Python实现的多好…但是越学越发现,膜拜詹姆斯.高斯林,这真是个神人,看似繁琐的每一步,都是精简到不能再精简的精粹,当我第一次了解到JAVA的垃圾内存回收机制,真的是感动,自惭形秽啊!
不多说太多了,还是讲点正经事吧。
java的运行机制
JAVA语言的运行机制说来也有意思,他是先编译在执行,这个看起来就像是一句废话(注:高级语言分为解释性语言如python,还有编译性语言如JAVA,C,C++),但是就是这么一个小步骤,使JAVA语言实现了跨平台的功能,而这一切都源于一个东西,他的名字叫做JVM,对于jvm来说,也就是java虚拟机,他实现了将.java文件编译成.class的功能,text.java在运行的时候回首先被jvm编译为text.class文件,之后再被JRE运行 对应命令分别为javac java。
此外值得一提的还有一个比较重要的东西叫做jdk,这个东西叫做java development kit,这个是给开发者使用的,内置jvm和jre,也就是java程序开发者的程序包,里面有很多的jar包,那么jar包是什么呢?jar包简单来说就是很多类的结合,像我们常见的java.util.*;这就是个jar包,所以对于面向不同的开发应用的jdk之间的不同 主要是在于jar包的不同。
java的数据类型与应该掌握的基本知识
注释
这个地方我必然要提一下注释的重要性,因为对于开发一个工程来说,必然会产生很多的文件,而对于一个轮子的使用者来说,我是真的用不到去看你的底层,所以一定要写好注释,不然效率真的是底下。
注释的基本使用方法就是
//与/* /,一个是用于单行注释一个适用于多行注释,这个就这样,我下面主要说一下文档注释。
我这里只是简单提一下语法,至于更加深入的实现,还希望各位看官,自己手动敲一敲。
文档注释的开头是 /**,结尾是通过/实现,这其中的所有内容将全部被提取到API文档中,之后我们需要使用javadoc命令进行文档提取,值得一提的是被提取的内容,我们应该使用html的方式进行书写
javadoc常用的标记主要有
@author
@version
@version
@deprecreated
@return
@see
等等,这里因为时间原因,就不一一列举了,以后有时间再来补充。
java的数据类型
java的数据类型主要包含引用数据类型和基本数据类型,这个地方简单提一下,对于引用数据类型理来说的话,复制语句的等号,只是传递了一个引用,so,right?你懂我意思吧,就是说,如果说 c 是一个引用数据类型的话,我们使用 a =c的话对a做操作实际上就是对c做操作。
对象转型
有关更详细的内容在JAVA笔记01中已做详细讨论,在此开始讨论对象转型,对象转型针对的是引用和对象不是一个类型的情况,比如
父类和子类的关系
主要分为一下几类:
- 子类转父类(显然可以,向上转型即 super = child)
对于这种情况Hero hero = APHero如果想要调用孩子的方法则需要使用((ADHero)hero).method(); - 父类转子类(可以,但是可能会发生异常child=super,同时需要加上强制类型转换)
比如
ADHero adHero = new ADHero();
APHero apHero = new ApHero();
Hero h = adhero
apHero=h//会发生错误因为AP和AD英雄并没有继承关系 - 没有继承关系的两个类相互转换一定会失败
- 实现类转化为接口(向上转型)转换是能成功的
ADHero hero = new ADHero();
ad adj = hero - 接口转换为实现类(向下转型,如果是有实现继承关系的是可以成功的,如果没有则不可,类似于父类向下转型)
一言以蔽之:父子可能可以呼唤,子转父一定可以,兄弟一定不行,接口父类如是
instanceof函数,判断一个引用所指向的对象,是否是Hero类型,或者是Hero的子类,但是如果这个引用并没有指向对象即
hero h ;则h instanceof hero是false
方法重写与多态
孩子有和父类相同的函数,则子类覆盖掉父类的属性方法,这叫做重写,如果是子类覆盖掉父类的类方法,这叫做隐藏
对于子类来说,如果对于函数名相同的函数,如果参数不同,完成不同的功能就称作为多态,或者不同的子类函数实现的功能不同,也叫做多态
super精讲
对于一个子类来说,在进行初始化的时候是首先执行父类的构造方法之后再执行自己的构造方法。
- super提供两个构造方法
一种是带参数,一种是不带参数的 - super另一个重要作用是使用super来调用当前父类的属性或方法,如果当前子类已经对方法执行了重写,则可以通过super进行调用
super.number
super.getnumber()
思考 如果父类没有无参构造方法子类如何构造
在子类构造器中应首先显示给出父类的有参构造方法。
JAVA超类
Object是所有类的父类,什么一个类默认是继承了Objects类
Object类提供了一下主要方法
这些方法都需要重写
- toString()
返回当前对象的字符串表达 - finalize()
当一个对象没有任何引用指向时,JVM就会调用这个函数 - equals()
用于判断当前两个对象的内容是否相同 - ==
用来判断当前的两个引用是不是指向同一个对象 - hashCode()
返回对象的一个哈希值 - 线程同步方法
wait()
notify()
notifyAll() - getClass()
返回一个对象的类对象,用于反射机制,反射就是根据类名创建对象
final精讲
final可以修饰方法、类、引用、基本类型变量
- 当final修饰类的时候表示类不能被继承
- 当final修饰方法的时候表示方法不能被重写
- 当final修饰基本变量的时候表示其只有一次赋值机会
- 当final修饰引用的时候表示只有一次指向对象的机会
String为什么不能被继承
特别注意String不能被继承,因为String时final的,所以不能被继承
原因如下:String被设计为final是有原因的,因为String这个类使用得实在是太广泛了,如果能够被继承,就意味着其子类可以随意重写其非final的方法,这些方法就有可能变得和期望的不一样,比如toString始终返回空。 这样就给软件逻辑带来了很大的不确定性因素。
抽象类
抽象类中可以有抽象方法,也可以没有抽象方法
抽象方法举例
public abstract void attack();
类名为public abstract class A{}
一个类只能继承一个抽象类,如果继承了该抽象类则必须提供抽象方法的实现(ps:JAVA只支持单继承,默认情况下所有的类都继承Objects)
对于每一个实例来说同样需要提供不同的抽象方法的实现。
与接口的区别
对于抽象类来说没办法直接声明实例,但是接口可以声明实例,一个类可以继承多个接口,但只能继承一个抽象类,因为抽象类的本质时class,而接口是interface
内部类
分为以下四类:
- 非静态内部类
类中有类,只有当外部类存在时才有意义,比如英雄的分数中的分数类,其创建需要依赖与外部类
public class Hero{
class score{
int kill;
int die;
int assit;
}
public static void main(String[]args){
Hero h = new Hero();
score s= h.new score();
score ss = new Hero().new score();
}
}
- 静态内部类
对于静态内部类来说,可以直接实例化,而不需要使用外部类,其意义代表所有创建外部类的属性有且仅有这一个属性类,他们对这个类的操作会影响到所有的实例。
对于静态内部来来说无法访问外部类的实例方法,只可以访问私有静态成员 - 匿名类
声明一个类的同时实例化一个类,通常情况下要使用一个接口或抽象类,都必须创建子类
Item是一个抽象类,在我们呢使用这个抽象类的过程中直接对里面的抽象方法进行了实现
此时他已经是个新类,但是并没有名字
Item t2 =new Item() {
@Override
public boolean disposable() {
return false;
}
};
- 本地类
和匿名类一样不过区别在于本地类有了自定义的类名
public static void main(String[]args){
class someHero extends Hero{
public void attack(){
System.out.println( name+ " 新的进攻手段");
}
}
SomeHero h =new SomeHero();
}
在匿名类中访问外部的局部变量,外部的局部变量必须修饰为final,在jdk中已经不需要强制修饰成final,编译器已经在编译时加上了final
默认方法
在jdk8中已经支持接口提供具体的方法了,但是需要加上关键字default,之前只能添加抽象方法
思考:如果继承多个接口的情况下,有同样的attack函数怎么办
实现类必须重写该方法
小结
类继承—>子类完全继承父类特点
抽象类继承—>继承时抽象的部分不同的子类可以有不同的实现
接口继承—>所有成员在子类都可以有不同的实现
至于为什么要用接口而不是抽象类
这要看二者适用的情况
当个性大于共性时,适合接口,如鸟和飞机,适合抽象出一个飞的接口
当共性大于个性时,适合抽象类,如老鹰和麻雀,适合抽象出一个鸟的父类
另外接口可以实现多重继承,这也是一个特点。
容易混淆的误区——实现抽象方法与重写普通方法 的本质
抽象方法与重写的目的都是为了实现多态,
相同点:两者方法体和参数都必须和父类保持一致,
不同点:抽象类没有方法体,重写有, 抽象类比重写更加灵活。
只不过抽象方法在父类中不需要写方法体,并且子类中必须重写该抽象方法。
所以说抽象方法其实就是重写的一种罢了。
抽象类的实现和正常类的重写没区别。
接口的应用场景——继承、实现的选择
1.因为接口的属性和抽象方法默认是必须公开的(public)
所以如果有需要保护private(私有)的属性或者方法时,必须用继承一个类(抽象类也是类)
2.继承类(一般私有)只能继承一个(单继承),实现接口(公共)可以实现多个(多继承)
所以能用接口解决的问题,基本不用继承一个类(或抽象类)来解决
3.接口之所以提供默认方法,只是为了不用实现,直接可以用(提供方便而已,不要多想)
4.之所以会有抽象类这种类,只是为了在继承私有属性和方法的同时,子类约定好必须使用这个方法。因为继承的普通方法可以不用写出来,而抽象方法必须写出来(只是为了提醒程序员其中重点特殊的功能是什么)
所以如果需要继承父类私有属性的同时,又需要公共的特殊功能时,可以考虑抽象类
5.抽象类是对对象进行的抽象,而接口是一种行为规范
6.二者的选择
(1)优先选用接口,尽量少用抽象类
(2)需要定义子类的行为,又要为子类提供共性功能时才选择抽象类。