公司的这几天iOS面试

作者: 一直搬着砖 | 来源:发表于2017-02-22 13:13 被阅读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可以类比过来。具体代码晚点发出来。

    相关文章

      网友评论

        本文标题:公司的这几天iOS面试

        本文链接:https://www.haomeiwen.com/subject/vttmwttx.html