1、static
static基本通用,在java中的static可以修饰方法,而oc不能用static修饰方法(原因是java的方法就是函数)。
2、 method
java中的方法和函数是一个意思,而oc中的方法和函数是两中写法。
3、final
java中有final修饰符,oc没有,但是swift有。final可以修饰类,方法,变量。final修饰的方法不可以被覆盖、和继承,修饰的成员变量只能赋一次值等等。注意swift中final不能修饰结构体和枚举。
4、构造器
java有构造器,oc有init方法。
5、继承
java和oc都有继承,区别:
oc:
OC中不允许子类和父类拥有相同名称的成员变量名;(java中是可以的)
编译器从上往下执行,所以在子类前面至少应该要有父类的声明
OC中的子类可以拥有和父类相同名称的方法,在子类调用时,优先去自己的内部寻找,如果父类没有定义该方法,则继续在继承链上查找,直到找到为止,如果找到NSobject为止仍然未找到,则报错;
子类允许重写父类的方法,在调用子类对象的重写方法时,就会调用重写后的方法;(与java中子类重写父类中的非静态方法是一样的)
如果在子类中 需要调用父类的功能,可以借助super关键字(与java一样)。
java:
注意:静态代码块不管创建多少个对象只执行一次,非静态代码块随着对象的创建而执行,并且总是在构造方法的前面执行。
父类的静态代码块—>子类的静态代码块—>主方法(执行哪个程序就执行哪个程序的主方法)—>父类的非静态代码块—>父类的无参构造函数—>子类的非静态代码块—>子类的无参构造函数(若实际子类执行的是有参构造函数,则不执行无参构造函数)—>成员函数(指的是非静态方法)(指定执行哪个就执行哪个成员函数,若重写了父类成员函数,则只执行子类的成员函数)
在多态的时候子类重写父类的静态方法会调用父类的静态方法,而子类重写父类的非静态方法后就调用的是子类的非静态方法。如果你试图重写静态方法,Java不会阻止你这么做,但你却得不到预期的结果(重写仅对非静态方法有用)。重写指的是根据运行时对象的类型来决定调用哪个方法,而不是根据编译时的类型。父类的非静态方法与子类的非静态方法名相同(包括参数),那才叫做重写,因为他们访问的是同一个内存空间。
一个类的静态方法和静态变量使用原理,JVM会把类的这个静态方法和静态变量在类加载的过程中读入内存(事实上是方法区),相当于常驻内存。也叫做类加载,static 修饰的 在JVM运行时就加载到内存中了 所以不需要实例类
大家都知道,在程序中任何变量或者代码都是在运行时由系统自动分配内存来存储的,而所谓静态就是指在第一次分配内存后,所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。这样做有什么意义呢? 在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用static声明的(在这里所讲排除了类的访问控制),因为static修饰的方法在编译时就进行静态绑定了,每个静态方法都在不同的内存空间,所以还是调用父类的静态方法。
结论:OC中的继承是先到子类中找,找不到再到父类中找。java中的继承是先到父类中找,找不到再到子类中找。
6、abstract
java有抽象类 abstract,而oc没有,抽象类的特点是:只有方法的声明没有实现,需要用abstract修饰,并且抽象方法必须定义在抽象类中,该抽象类也必须用abstract修饰,抽象类不能被实例化,因为没有方法的实现部分,调用抽象方法也没有任何意义,并且抽象类必须有字类覆盖所以抽象方法,这样子类才可以实例化,否则这个子类还是抽象类。根据以上种种描述,oc也可以实现抽象类,通过协议定义接口,父类(抽象类)遵守协议并实现方法,在方法里定义异常,当子类没有实现该方法就会走父类(抽象类)方法从而抛出异常,从而模拟【子类必须实现所以抽象类方法】的功能。oc的这种模式在许多大型框架或者sdk中非常常用。
抽象类不能被private、final、static共存。
7、接口
java和oc的接口模式区别:interface、implement以及oc中的protocol;
java和oc都是单继承模式,所以就出现了接口的多继承来弥补短版。多继承接口不会出现混乱,因为接口里没有实现部分,即使有相同方法名也不会出现问题。
java
在java中的interface是‘接口’的意思,而java的类声明用class,即接口用interface声明,类是用class声明,是两个独立的部分。
只有在类声明要实现某个接口时,他们两者才建立了关系
oc
网上大家都将oc中的interface理解为“非正式协议(或说接口)”,prototal理解为“正式协议(或说接口)”,我觉得那样理解起来虽然不困难,但是很变扭,于是我做一点自己的理解:
protocal就相当于java中的interface;
而interface和implementation共同代表一个类,两者的组合相当于java中的class,即oc中的类必须包括两部分,interface部分和implementation部分,这才是oc中的一个类的完整声明;然后OC中将成员变量和成员方法的声明部分放置在interface部分中,包括继承关系,protocal实现关系,都在interface里面的头部进行声明,然后将实现部分放置在implementation部分中,相当于是将类拆分成声明和实现两部分,这两部分缺一不可,所以在OC中,不妨不要将interface叫做接口,直接叫做类声明部分来得容易理解多了,简而言之,oc中interface是类的一个部分,和implementation共同组成一个完整的类。
8、多态
都有多态,java和oc基本一样。对于staitc修饰的静态方法,在继承那解释了静态方法区别,所以可以这么认为,静态方法不存在多态。因为静态方法可以不用对象来调用,所以也就不存在多态。
9、内部类(OC没有内部类)
Java的四种内部类包括如下:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
10、异常处理
都分可处理和不可处理,NSError不处理。下面是处理的方法:
try…catch 是捕获异常(自己处理)
throw 是抛出异常(交给上一级处理)
java:
try…catch…
try….finally……
try….catch…finally…
oc:
@try{
......
}@catch (NSException *exception) {
......
}@finally {
......
}
java和oc一样,都用自己处理异常的类,java是exception,oc是NSException。
但是我个人觉得还是oc的异常处理要好用(可能是我对java还是不熟悉的原因)。
比如知道具体位置用try catch,不知道具体位置就可以用UncaughtExceptionHandler可以检测出常见错误,并友好的提示用户。
例如:
NSArray、NSDictionary、NSString、KVC等问题引起的闪退。
解决NSObject performSelector找不到selector引起的闪退。
使用方法:
首先需要在appDelegate中使用InstallUncaughtExceptionHandler()用于监听
添加UncaughtExceptionHandler这个类
iOS SDK提供的函数是NSSetUncaughtExceptionHandler来进行异常处理。但是无法处理内存访问错误、重复释放等错误,因为这些错误发送的SIGNAL。所以需要处理这些SIGNAL
针
对上面的问题对于java,我目前还不了解,后续继续深入学习再补充。
11、package
java:
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。
作用:
- 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
- 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
- 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
Java 使用包(package)这种机制是为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)等。
oc:
oc没有package,但是oc有@package。具体:@private、@protected、@public、@package,用来显示访问权限的。所以和java的不是一个东西。
- @private 私有的
私有,也就是只有自己有,别人谁都不可用,哪怕亲如自己的孩子。
- @protected 受保护的
相较上边的private而言,就咩有那么自私了,他自己可以用,自己的孩子也是可以共享的
- @public 公共的
相较上边而言,那就牛了,谁都可以用,只要你有这个类的对象,就可以拿到public下的变量,够无私了吧
- @package 包
这个主要是用于框架类,使用@private太限制,使用@protected或者@public又太开放,就使用这个package吧。
12、jar、framework 和.a
java有jar、ios有framework(动态库、静态库)和.a静态库;
jar如何生成很简单,不做赘述。
oc:
framework分静态framework和动态的framework。一般三方平台提供的大多都是静态的framework,而动态的framework早期是只有系统才用,而到ios8以后才对外开放的。还有.a静态库,市面上使用的频率相对于静态的framework要少很多,大家可以百度framework和.a的性能、包大小已及【库的瘦身】,就可以充分理解了,具体原因我就不赘述了。
13、GC
垃圾回收机制的(Garbage collection简称GC)
java支持支持垃圾回收机制,System.gc();可以回收垃圾。
oc也是支持垃圾回收机制的:
- OC是支持垃圾回收机制的。
- macOS开发中是支持的,但是iOS中,是不支持GC的。
- iOS开发只支持手动内存管理和ARC,Mac开发支持GC垃圾回收机制, 18.8之后弃用了GC,开始使用ARC
- iOS开发是支持ARC(Automatic Reference Counting的简称),ARC是在IOS5之后推出的新技术,它与GC的机制是不同的。
14、多线程
java:Thread
在java中要想实现多线程,有两种手段,一种是继承Thread类,另外一种是实现Runable接口
oc:pthread、NSThread、GCD、NSOpration、RunLoop、AutoreleasePool
oc就不在这啰嗦了,个人感觉oc的好用,尤其是NSThread、GCD、NSOpration三类用起来很爽,比java好用多了(不排除java刚学用不习惯的因素?)。
15、字符串
java:String、StringBuffer和StringBuilder
-
String是内容不可变的,而StringBuffer和StringBuilder都是内容可变的。
- StringBuffer是同步的,数据安全,效率低;
- StringBuilder是不同步的,数据不安全,效率高。
oc:NSString、NSMutableString
oc的字符串不像java的StringBuilder,oc所有属性的安全与否是通过声明为原子性(atomic)和非原子性(nonatomic)来确定的。atomic线程安全,效率低,nonatomic线程不安全,效率高。
16、集合
-
oc中的有序集合NSArray与NSMutableArray
oc中的数组存放的内容是对象,不能进行对基本类型数据进行存放,但是oc中的一个数组对象可以存放不同类型的对象,而java中的数组可以存放基本的数据类型。
oc中如果想对基本类型数据进行存放的话需要把其转换成对象进行存放。转换的方法有:NSNumber,NSString。
- oc中的无序集合NSDictionary与NSMutableDictionary。
oc字典与java中的集合map类似都是键值对,都是通过相应的key去去到对应的value。都是无序的,但是map中有其他的类型如hashmap这样就可以让map中的值变得有序起来,相应的字典暂时未发现相应的方法。
java的所有集合类:
①、Iterator:迭代器,它是Java集合的顶层接口(不包括 map 系列的集合,Map接口 是 map 系列集合的顶层接口)
②、Collection:List 接口和 Set 接口的父接口
③、List :有序,可以重复的集合。由于 List 接口是继承于 Collection 接口,所以基本的方法如上所示。
④、Set:典型实现 HashSet()是一个无序,不可重复的集合
⑤、Map:key-value 的键值对,key 不允许重复,value 可以
⑥、Map 和 Set 集合的关系:(1)都有几个类型的集合。HashMap 和 HashSet ,都采 哈希表算法;TreeMap 和 TreeSet 都采用 红-黑树算法;LinkedHashMap 和 LinkedHashSet 都采用 哈希表算法和红-黑树算法。(2)分析 Set 的底层源码,我们可以看到,Set 集合 就是 由 Map 集合的 Key 组成。
注意:针对list:
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
- 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
集合关系图:
oc集合类:
- NSArray和NSMutableArray
-
NSDictionary和NSMutableDictionary
-
NSSet和NSMutableSet:集合相比于字典,除了可以快速插入,删除之外,还能快速判断一个对象是否在集合中,因为集合的实现使用了哈希算法。集合储存的对象是唯一的,不会相同,所以,无论加进去多少个一样的对象,集合里面永远只会有一个对象。如果不在意数组的顺序,可以用集合代替。
17、数据的读写
oc的写入和读取简直就是java序列化和反序列化的翻版
在iPhone 的.ipa 文件中,经常可以看到.plist 文件,它保存了程序的相关属性,叫做属性列表。其实它就是NSArray、NSDictionary、NSString、NSData 持久化之后的文件。
这几个类型都有一个成员方法 writeToFile: (NSString) file atomically: BOOL 用于将自己写入到一个文件。atomically 为YES 表示文件先存储到临时文件区,如果文件保存成功,再替换掉原始文件,这样的好处是可以防止在保存文件过程中出错,但是仅适用于小文件,因为你相当于是在临 时文件存储区也放了一份,再加上原始文件,就是两份文件,如果文件比较大,将会占用较多的用户的磁盘空间。
如果你要持久化的类型不是上述的数组、字典、缓冲区,那该怎么办呢?Objective-C 中也有和JAVA 一样的序列化、反序列化支持,使用NSCoding 协议。NSCoding 协议定义了如下两个方法:
-(void) encodeWithCoder: (NSCoder) coder;
-(id) initWithCoder: (NSCoder) decoder;
第一个方法相当于编码对象,第二个方法是解码回对象,也就相当于给类型定义了一个新的init 方法而已。
对象的复制
对象的复制就相当于JAVA 中的clone()方法,也就是对象的深度复制,所谓深度复制就是重新分配一个存储空间,并将原对象的内容都复制过来,从这些描述可以看出,复制也会分配空间,那就是你要对复制出来的对象release,就是前面所说的alloc、new、copy 操作创建的对象,要手工release。
Objective-C 中的一个对象是否可以被复制,要看它的类型是否遵循NSCopying 协议,这个协议中有个复制方法-(id) copyWithZone: (NSZone) zone 需要我们去实现。
java类:
oc:
1. NSFileManager:如果,只需要管理文件和目录,程序可使用NSFileManager 进行管理,包括创建,删除,移动,复制文件等;
2. NSFileHandle: 如果程序需要读取文件内容,则可通过NSFileHandle进行处理;;
3. NSURL:如果要读取网络资源,则可以通过 NSURL 进行处理;
4. NSBundle:如果只是读取项目内部的资源,则可 借助 NSBundle 进行处理。