首页投稿(暂停使用,暂停投稿)iOS学习

公司的这几天iOS面试

2017-02-22  本文已影响0人  一直搬着砖

我们公司准备新招一个iOS开发,要求是中上的水平,然后让我出一套面试题。我认为既然是中上水平,那么基础和项目实战都要考,我自己也应该只能算中等水平。然后,我就出了一套题,没想到的是我出的第一题,竟然到现在还没有一个人答对(我们喊过来面试的都是毕业2年以上的)。我问了下同事,他们说,这个题有点刁钻。题目内容是这样的:
NSString *s1 = @"Hello world"; NSString *s2 = @"Hello world";请问 s1 == s2的返回值是YES还是NO? 写法①
很刁钻吗?这个不应该是基础题吗?

针对评论说,没有给答案

首先这道题的答案是:YES。其实,这道题真的不刁钻,刁钻的题可能是下面这样:
NSString *s1 = @"hello"; NSString *s2 = [[NSString alloc] initWithString:s1];请问s1==s2的返回值? 写法②
或者是下面这样:
NSString *s1 = [NSString stringWithFormat:@"hello"];NSString *s2 = [NSString stringWithFormat:@"hello"];请问s1==s2的返回值? 写法③
当然,上面的这几种写法,答案都是YES。可能学习Java的人,现在会有疑问了,可能认为写法②和写法③都应该是不相等的。
这道题考的两个字符串是否相等,这里的相等是绝对相等,不是isEqualToString的方式,比较是两个字符串的内存地址是否一样。那这里就要从字符串在内存中的存储区间来看了,记得在Xcode6以前,字符串的定义还可以这么写:NSString *s2 = [[NSString alloc] initWithString:@"hello"],但是Xcode 6以后,这种写法就会有警告,说明编译器在字符串的存储这一块做了改变。

运行结果
不管是直接定义一个字符串常量还是使用allocinit的方式,字符串的存储都是在常量区,至于常量区是在堆区还是栈区,这个需要查证,因为不同的版本可能会有变动(java也是在Java7做了改变),而使用stringWithFormat方式创建的字符串,如果字符串相同也是只有一份,但是很明显,不是放在常量区的。也就是说使用同样的方式创建的相同的字符串(NSString)都是只有一份的。(NSMutableString是不一样的)
那是不是所有的字符串都是存在常量区呢?答案是否定的。你可以试着把NSString换成NSMutableString试试。很显然,这道题答对或者答错基本不会影响开发,但是,它是基础,也同样重要。

还有一道题是关于深拷贝和浅拷贝的区别,我发现也是基本没人说明白,我就在网上搜索了一下,发现网上的大多数答案也是出乎意料的大面积错误,也有正确的,但是很少。很多博客都是说的,浅拷贝是指针拷贝,深拷贝是重新创建对象。凡是这么答题的,我都会问他们指针拷贝是否就是两个不同引用指向同一个地址,他们大多也给了我肯定的答案。

我记得在学习Java和C++的时候,老师都讲过这个问题.。
Java里面的浅拷贝是实现Cloneable接口,实现里面的clone方法,类似下面这样:

class B implements Cloneable {
    String name = null;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        return super.clone();
    }
}

 class A implements Cloneable
{

    B b = null;
    public A() {
        b = new B();
    }
    @Override
    protected Object clone()  {
        // TODO Auto-generated method stub
        A a = null;
        try {
            a = (A) super.clone();
        } catch (CloneNotSupportedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return a;
    }
}

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        A a1 = new A();
        a1.b.name = "a1";
        A a2 = (A) a1.clone();
        a2.b.name = "a2";
        
        System.out.println("第一个对象的name:"+a1.b.name + "第二个对象的name:"+a2.b.name);
    }
} ```

深拷贝则是下面这样:

class B implements Cloneable {
String name = null;
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}

class A implements Cloneable
{

B b = null;
public A() {
    b = new B();
}
@Override
protected Object clone()  {
    // TODO Auto-generated method stub
    A a = null;
    try {
        a = (A) super.clone();
                a.b = (B) b.clone(); // 差别就在这里。多了对实例变量的拷贝。
    } catch (CloneNotSupportedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return a;
}

}

public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
A a1 = new A();
a1.b.name = "a1";
A a2 = (A) a1.clone();
a2.b.name = "a2";

    System.out.println("第一个对象的name:"+a1.b.name + "第二个对象的name:"+a2.b.name);
}

}```
差别只是一个是换壳,一个是把壳子包括里面的内容都换了。有的人用公司打比方,就是一个是换了个公司名,里面的员工不变;另外一个是换了公司名,里面的员工参照原公司重新招。差不多就是这个意思,只是人不能clone。
Objective-C 里面原理是一样的,只是遵守的是NSCopying协议,实现里面的- (id)copyWithZone:(nullable NSZone *)zone;方法。

针对评论说没有给出答案

上面的java代码其实已经给了答案了,OC可以类比过来。具体代码晚点发出来。

上一篇下一篇

猜你喜欢

热点阅读