zoukankan      html  css  js  c++  java
  • 关于“构造函数”中的几个小问题,也许面试会问到哦~

       构造函数这玩意也是面试官经常会问到的东西,我们知道一个类的状态初始化就全靠它了,下面提几个小问题。

    Q:我看到Web项目里面通常都有一个BasePage页面,其中构造函数里面做了权限验证,

         请问为什么要这么做。

    A:  既然这么做了,那么设计者肯定就知道了一个原则就是实例构造器中,父类构造器先于子类执行,那么这个先执行就可

         以做很多有意思的事情,比如你说的权限验证,可能有人会问为什么要先于子类执行,刚才我也说了,构造函数是用于

         初始化本类状态的,这也叫“先扫屋子再请客”的道理吧~,然后风雨兼程的回溯到Object的ctor中。好了,现在来回答

         你的问题,先把这个问题简化一下,就不用web项目来演示了。

     1     public class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             var b = new Bird();
     6 
     7             Console.Read();
     8         }
     9     }
    10 
    11     public class Animal
    12     {
    13         public Animal()
    14         {
    15             Console.WriteLine("running first... i'm animal, all must be running after me.");
    16         }
    17     }
    18 
    19     public class Bird : Animal
    20     {
    21         public Bird()
    22         {
    23             Console.WriteLine("the next... i'm a cute bird.");
    24         }
    25     }

    可以看到,确实Animal于Bird先执行,可能有人会问,那Animal调用的是谁的ctor呢?当然就是Object了,我们可以看看IL:

    Q: 既然你说构造函数用于初始化类的初始状态,那么请问下,我现在有一串这样的

        json:{"Name":"smart","Age":2}。实体类如下图,请问我的json序列化后,Age=?

     1     [Serializable]
     2     public class Bird
     3     {
     4         private string name = "smart";
     5 
     6         public string Name
     7         {
     8             get { return name; }
     9             set { name = value; }
    10         }
    11 
    12         private int age = 2;
    13 
    14         public int Age
    15         {
    16             get { return age; }
    17             set { age = value; }
    18         }
    19 
    20         public Bird()
    21         {
    22             Age = 5;
    23         }
    24     }

    A:其实这个问题的关键在于,反序列化的时候是否会调用构造函数的问题,先来通过Reflector看下源码,发现并没有代码,觉得

        有点小奇怪,就用ILSpy反编译一下,同样也没有代码,不可否认,底层肯定是有代码执行的,要么反编译不出来,要么clr用了

        其他的方式,反正我们看不到实现源代码,如果大家有什么好意见可以帮帮我,谢谢了

    Reflector截图:

    ILSpy截图:

    据资料说,里面最后调用了FormatterServices里面的GetSafeUninitializedObject来分配对象内存,分配完后就不走构造器

    了,所以针对这个问题,只能记住了。最后为了验证一下,执行完代码之后确实没有走构造函数。

    Q:我知道引用类型可以用构造器,那值类型为什么不能定义无参构造器?

    A:这个问题问的好,编译器会根据性能考虑,不会调用值类型的构造函数,即使你强制的new一下也不会执行

     1 namespace Sample
     2 {
     3     public class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             Point point = new Point();
     8         }
     9     }
    10 
    11     public struct Point
    12     {
    13         public int Age;
    14     }
    15 }

    不过除非你自己显示定义有参构造函数,而且值类型有个特点就是读取之前必须初始化,否则会编译不通过。

    Q:请问在类构造函数中能做单例吗?

    A: 能不能做,就要看类构造器的特征了,我们知道类构造器跟实例构造器一样,他是用来初始化静态字段的,线程

         访问类构造器的时候内部会进行加锁处理,所以多个线程同时访问的时候,只会有一个线程执行了类构造器,所以

         确实可以。

  • 相关阅读:
    Arduino语法-变量和常量
    Arduino-函数库和程序架构介绍
    第十章浮力题汇总
    pyqt5-按钮基类-QAbstractButton
    在Windows上安装Arduino-IDE
    Arduino-接口图
    python-文件及文件夹操作
    Qt WebRTC demo
    多线程使用信号量sem_init,sem_wait,sem_post
    华为公司内部培训资料_介绍RTSP的消息、信令等
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/3931564.html
Copyright © 2011-2022 走看看