精华内容
下载资源
问答
  • 几年前,我在大学里学习过面向对象编程和设计,我记得讲师对使用静态变量或静态方法人非常生气,因为他们把静态描述成一个非常糟糕设计。我理解是静态类型东西,是获得全局"视觉"东西,也就是说,它可以...

    本问题已经有最佳答案,请猛点这里访问。

    Possible Duplicate:

    Why are static variables considered evil?

    几年前,我在大学里学习过面向对象的编程和设计,我记得讲师对使用静态变量或静态方法的人非常生气,因为他们把静态描述成一个非常糟糕的设计。

    我的理解是静态类型的东西,是获得全局"视觉"的东西,也就是说,它可以被任何东西访问。

    我的理解正确吗?有没有关于静态的使用的信息会使它不能正常使用?有没有一种方法可以避免在代码中使用静态变量或方法?

    顺便说一句,我知道静态主方法是成功运行应用程序的前提。

    为什么静态变量被认为是邪恶的可能的复制品?-注意:链接只寻址静态变量。静态方法没有任何错误-请参见例如:stackoverflow.com/questions/2671496/…

    静态变量或方法没有问题。这只是因为对于OOP,您希望尽可能多地将行为与对象关联起来,这意味着使用实例方法和变量。尽管如此,在某些特定情况下静态成员是必要的:构造函数(如您所提到的)和单例模式是很好的例子。

    例如,它违反了多态性概念

    静态变量和静态方法是完全不同的。

    静态变量是坏的,除非它们代表某种类型的"singleton",如果它们代表,那么在OOP中,最好创建实际的singleton类(特别是如果可以使用枚举singleton)。另外,静态变量使多线程编程变得困难,甚至在单线程编程中也能做到这一点,在单线程编程中,您"意外"需要两个带有静态字段的类实例。

    另一方面,静态方法一般都很好,只要它们不访问任何静态数据,而是只对它们的参数进行操作。当然,如果你注意到你有static void MyStaticUtils.operateOnFoo(Foo foo),那么最好使用非静态void Foo.operate()方法。但有时您没有向现有类添加方法的奢侈,必须对现有方法返回的实例进行操作,然后静态实用程序方法绝对是不错的选择。

    静态主要用于访问类成员而不创建类实例。正如您所知,我们为什么要在运行时编写public static void main(),而jvm只需bcoz就可以访问这个方法,而无需创建类对象和启动程序。

    它取决于您的要求,即如何使用或说如何使用访问说明符声明类的成员为私有、公共、默认和保护访问级别,而静态的则将其作为静态访问级别。

    如果不使用static,则必须将成员声明为public,或者如果继承了类,则也将其设置为protected。与在同一个包中一样,您定义了类,然后只定义了用于继承类的静态类。如果不使用inhert类,则需要创建该类的对象,然后可以访问其中的成员(请注意,它基于访问说明符)。

    下面是详细信息的链接

    http://xahlee.info/java-a-day/access_specifiers.html

    http://www.javabeginner.com/learn-java/introduction-to-java-access-modifiers

    使用静态变量的主要合法情况是单例模式,而且没有其他方法可以做到这一点。

    单例访问器方法,尤其是使用延迟初始化的访问器方法,需要静态方法。

    单身没有什么"坏"的。

    你能解释一下吗?

    展开全文
  • JVM方法区变革

    2020-07-20 18:07:22
    学习JVM必看书籍无疑是《深入理解Java虚拟机》这本书了,在书中,关于运行时数据区域模型是这样描述的: 在这里我们只针对HotSpot VM来说,它是OracleJDK和OpenJDK中所带虚拟机,也是目前使用范围最广Java...

    学习JVM必看的书籍无疑是《深入理解Java虚拟机》这本书了,在书中,关于运行时数据区域模型是这样描述的:

    image-20200719214356251

    在这里我们只针对HotSpot VM来说,它是OracleJDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。在JDK7之前,这样的模型是正确的。但是到了JDK8,如图标红的部分,做了一些优化。

    什么是方法区,什么是永久代,运行时常量池又是什么

    • “方法区”(Method Area),是线程共享的区域,用于存储已被虚拟机加载的类信息,常量,静态变量等数据。首先我们要知道,方法区是JVM的一种规范,是一个概念,而这个方法区的具体实现由各个虚拟机厂商去实现。
    • “永久代”(Permanent Generation)就是HotSpot虚拟机对于方法区的实现,也仅仅是针HotSpot才有的。
    • “运行时常量池”是方法区的一部分。用于存放编译期生成的各种字面量和符号引用。其特性是具备动态性。

    优化一:字符串常量池从永久代划到Java堆

    由于常量池具备动态性,在程序运行过程中会有大量的字符串常量在运行时常量池里产生,此时如果放在永久代,则无法恰当的设定永久代的大小,容易出现性能问题和内存溢出。下面一个例子证明在JDK8中,字符串常量池已经放在堆中:

    String.intern()方法的作用是返回一个字符串引用,引用的是字符串常量池中的字符串(字面量),我们先来验证一下这个方法:

    public class StringConstantsPoolTest {
        public static void main(String[] args) {
            String str = "abc"; //  str存储在常量池
            String str2 = new String("abc");  // str2 存储在堆中
            System.out.println(str == str2); //  结果为false ,堆中的引用并不等于常量池中的引用
            str2 = str2.intern(); // 获取str2在常量池中的引用
            System.out.println(str == str2); 
        }
    }
    

    结果如下:

    image-20200719214443308

    证明 String.intern()方法返回了一个在常量池中的引用。 下面验证字符串常量池在堆中: 设置JVM参数:

    -Xms10m -Xmx10m -XX:-UseGCOverheadLimit

    public static void main(String[] args) {
            List<String> list = new ArrayList();
            int i = 0;
            while(true){
                list.add(String.valueOf(i++).intern());
            }
        }
    

    结果如下:

    image-20200719214507696

    我们看到这时报的是Java堆空间内存溢出,说明字符串常量池是在堆中,注意,此时仅仅是字符串常量池转移到了堆中,但是运行时常量池依旧还是在方法区里

    优化二:移除了永久代,引入“元空间”(Metaspace)

    为什么移除永久代?

    1. 方法区大小难以设定,容易发生内存溢出。永久代会存放Class的相关信息,一般这些信息在编译期间就能确定大小。但是如果是在一些需要动态生成大量Class的应用中,如:Spring的动态代理、大量的JSP页面或动态生成JSP页面等,由于方法区的大小在一开始就要分配好,因此就能难确定大小,容易出现内存溢出
    2. GC复杂且效率低。方法区存储了类的元数据信息和各种常量,它的内存回收目标理应当是对这些类型的卸载和常量的回收。但由于这些数据被类的实例引用,卸载条件变得复杂且严格,回收不当会导致堆中的类实例失去元数据信息和常量信息。因此,回收方法区内存不是一件简单高效的事情。
    3. 促进HotSpot JVM与JRockit VM的融合。JRockit没有方法区,移除永久代可以促进HotSpot JVM与JRockit VM的融合。

    什么是元空间(Metaspace),为什么引入元空间

    元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制

    元空间的特点:

    1. 每个加载器有专门的存储空间。
    2. 不会单独回收某个类。
    3. 元空间里的对象的位置是固定的。
    4. 如果发现某个加载器不再存活了,会把相关的空间整个回收。

    总结

    最终JVM(HotSpot)运行时数据区域模型如下:

    image-20200719214532847

    展开全文
  • C语言入门一般.doc

    2020-12-07 11:55:00
    A顺序存储的线性结构 B链式存储的非线性结构 C限制存取点的线性结构 D限制存储点的非线性结构 3 | 关于C语言中的全局变量下列描述正确的是 A全局变量的作用域一定比局部变量的作用域范B静态类别
  • 9、下列有关数据库的描述正确的是()。 A、数据库是一个DBF文件 B、数据库是一个关系 C、数据库是一个结构化的数据集合 D、数据库是一组文件 我的答案:C 10、下列说法中,不属于数据模型所描述的内容的是...
  • 你必须知道495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    1.10 同一个静态(static)函数或变量的所有声明都必需包含static存储类型吗? 1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef) 1.13 对于用户定义类型,typedef和#...
  • 对象的使用包括引用对象的成员变量和方法,通过运算符·可以实现对变量的访问和方法的调 用,变量和方法可以通过设定一定的访问权限(见下面的例子)来允许或禁止其它对象对它的 访问。 我们先定义一个类 Point。 例子...
  • 61-70

    2019-07-09 10:41:59
    注:以下问题的部分解析并非全部是自己原创,只是为了...1、下列关于一个类的静态成员的描述中,不正确的是( ) A 该类的对象共享其静态成员变量的值 B 静态成员变量可被该类的所有方法访问 C 该类的静态方法只能...

    注:以下问题的部分解析并非全部是自己原创,只是为了便于以后复习,直接粘贴总结的答案,主要来源是七月在线中的解析部分。https://www.julyedu.com/question/selectAnalyze/kp_id/4/cate/C

    1、下列关于一个类的静态成员的描述中,不正确的是( )

    A 该类的对象共享其静态成员变量的值
    B 静态成员变量可被该类的所有方法访问
    C 该类的静态方法只能访问该类的静态成员变量
    D 该类的静态数据成员变量的值不可修改

    解释:选D

    用static关键字修饰的数据成员为静态成员。
    普通成员每一个对象都回创建一个,但静态成员是被同类的所有对象共享,可以被类的所有方法访问。
    静态方法只能访问静态方法和静态成员,不能访问任何非静态方法和和非静态成员。
    若静态成员变量没有被const修饰,则其值是可以修改的。
    补充:静态成员只能在类外进行初始化,只有静态常量整型数据成员才能在类中初始化。
    普通成员只有在创建了对象之后才可以存在,但静态成员只要创建了类,便存在了。
    普通成员的调用方法为对象名.成员名,静态成员还可以直接用类名作用域的方法调用
    类名::成员名

    2、C++将父类的析构函数定义为虚函数,下列正确的是哪个( )

    A 释放父类指针时能正确释放子类对象
    B 释放子类指针时能正确释放父类对象
    C 这样做是错误的
    D 以上全错

    解释:选A

    当创建一个父类的指针调用子类的对象时(CFather *fa = new CSon),若父类的析构函数不是虚函数时,释放父类指针时只会调用父类的析构函数;若父类的析构函数是虚函数时,将会先调用子类的析构函数,在调用父类的析构函数。

    3、以下关于STL的描述中,( )是错的。

    A STL容器是线程安全的
    B 当容量不够时,vector内部内存扩展方式是翻倍
    C std::sort可以是不稳定排序
    D std::string中可以存储多个’\0’字符
    E std::bitset是一个存储bit的STL容器
    F std::stack默认是用deque实现的

    解释:选A

    STL容器没有规定一定是线程安全,所以如果是多个写操作,使用时需要由程序员加锁来保证一致性。
    容量不够是,一种vector的实现方案的确是翻倍,当然也有扩大为原来的1.5倍等其他方案。std::sort的一种实现方案是当数据量大时,使用快速排序;如果数量中等,使用堆排序;如果少量数据,则使用插入排序;因此,它不是稳定的排序方案。
    std::string有长度字段,不以’\0’字符作为结束标志。
    std::bitset是记录0、1标志的容器,但需要初始化时指定长度,功能上类似压缩的0/1数组。
    deque是双向队列,一般是分块连续的;在实现时,往往使用deque来实现堆栈std::stack。

    4、程序出错在什么阶段( )

    #include < iostream >
    using namespace std;
    int main(int argc,char**argv)
    {
    http://www.sougou.com
    cout<< “welcome to sogou”<< endl;
    return 0;
    }
    A 编译阶段出错
    B 运行阶段出错
    C 编译和运行都出错
    D 程序运行正常

    解释:选D

    本题中的网址比较迷惑人,在C++中,单行注释以双斜杠(//)开头,即"www.sougou.com"是注释内容。
    而前面http是标签,标签命名规则和变量相同,后面跟一个冒号(:),标签提供了表示特定语句的方式,使用goto label(label表示标签名)可以无条件跳转到该语句。

    5、下面程序执行结果为【说明:x86_64环境】( )

    int a[4][4] =
    {
    { 1, 2, 3, 4 },
    { 50, 60, 70, 80 },
    { 900, 1000, 1100, 1200 },
    { 13000, 14000, 15000, 16000 }
    };
    int (*p1)[4] = a;
    int (*p2)[4] = &a[0];
    int *p3 = &a[0][0];

    printf(“%d, %d, %d, %d\n”,
    * ( *(a + 1) - 1),
    * ( * (p1 + 3) - 2) + 1,
    * ( *(p2 - 1) + 16) + 2,
    * (p3 + sizeof(p1)-3));
    A 16000,1101,13002,2
    B 4,2,3,60
    C 16000,2,3,2
    D 4,1101,13002,60

    解释:选D

    a+1指向第二行 * (a+1)指向第二行第一列,( * (a + 1) - 1)指向第一行最后一列,故* ( * (a + 1) - 1)为4;
    指针p1是一个指向含有4个元素的数组的指针,即数组指针。当p1与整数加减时,以4个整型值长度为单位进行调整, p1+3指向第四行, * (p1+3)指向第四行第一列,* (p1+3)-2 将指向第三行倒数第二列,故* ( * (p1 + 3) - 2) + 1为1101;
    指针p2和指针p1类型相同,初始值也都是数组a的首地址,分析同p2;
    指针p3是指向单个整型元素的指针,与整数加减时以1个整型值长度为单位来调整, 对于第4个输出值,指针p1的大小在x86_64环境下为8个字节,* (p3 + 8 – 3)结果为60。
    在不同的系统环境中,指针类型:32位系统4字节,64位系统8字节。

    6、void func()

    {
    char b[2] = {0};
    strcpy(b,“aaaa”);
    }
    以下说法哪个正确( )
    A Debug版崩溃,Release版正常
    B Debug版正常,Release版崩溃
    C Debug版崩溃,Release版崩溃
    D Debug版正常,Release版正常

    解释:选A

    func函数中,申请了2个char大小的内存空间,而实际写入的数据超出申请空间,执行strcpy函数虽然将数据写入但是破坏了后续的空间,在函数返回前收回申请空间时发现内存访问越界。由于Debug版中,存在相应的保护机制检查是否内存访问越界,而Release版则不会进行相应的检查,故前者崩溃,后者正常。

    7、在x86_64环境下,int(*b)[10][10]; sizeof(b)=( )

    A 8
    B 40
    C 80
    D 400
    E 800

    解释:选A

    b为一个指向二维数组的指针,即数组指针,故其大小为指针的大小,在该环境下为8。

    8、在面向对象软件开发中,封装是一种( )技术,其目的是使对象的使用者和生产者分离。

    A 接口管理
    B 信息隐藏
    C 多态
    D 聚合

    解释:选B

    9、声明一个指向含有10个元素的数组的指针,其中每个元素是一个函数指针,该函数的返回值是int,参数是int*,正确的是( )

    A (int * p[10])(int*);
    B int [10]* p(int*);
    C int (* (* p)[10])(int*);
    D int ((int*)[10])*p;

    解释:选C

    首先区分一下数组指针和指针数组。int (* p)[10]是一个数组指针,p是一个指针指向 int[10]数组, int* p[10]是一个指针数组,p是一个数组,数组每个元素是个指向int型的指针。
    一个指向含有10个元素的数组的指针就是(* p)[10]。返回值是int,参数是int* 的函数指针的定义为int ( * pf)(int * ) ,然后把( * p)[10]作为一个整体替代 pf,即int( * ( * p)[10]))(int * )。
    对于复杂指针的解析,有一个“右左法则”。对于C选项中的int ( * ( * p)[10])(int*),可以进行如下解析:首先找到那个未定义的标识符,就是p,它的外面是圆括号,左边是*,说明p是一个指针,然后(* p)右面是[],所以是数组指针, * p指向一个int[10]数组。再看左边,是个 * 号,表明数组的每个元素为一个指针。出括号再看右侧是(int * ),说明这是一个函数指针,所以这个数组中每个元素是函数指针,该函数的参数是int*,返回值是int

    10、下面描述中,正确的是( )

    A 基类定义的public成员在公有继承的派生类中可见,也能在类外被访问
    B 基类定义的public和protected成员在私有继承的派生类中可见,在类外可以被访问
    C 基类定义的public和protected成员在保护继承的派生类中不可见
    D 基类定义的protected成员在保护继承的派生类中可见,也能在类外被访问

    解释:选A

    在这里插入图片描述

    展开全文
  • 1.10 同一个静态(static)函数或变量的所有声明都必须包含static存储类型吗? 6 1.11 extern在函数声明中是什么意思? 6 1.12 关键字auto到底有什么用途? 7 类型定义(typedef) 7 1.13 对于用户定义类型,...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    1.10 同一个静态(static)函数或变量的所有声明都必须包含static存储类型吗? 6 1.11 extern在函数声明中是什么意思? 6 1.12 关键字auto到底有什么用途? 7 类型定义(typedef) 7 1.13 对于用户定义类型,...
  • volitate关键字

    万次阅读 2016-10-15 20:45:49
    1 关于volitate关键字,描述正确的是() A 用volitate 修饰的变量, 每一次的更新对其他的线程都是可见的; B 对volitate 的操作是原子性的 C 对volitate 的操作不会造成阻塞 D 不依赖其他的锁机制,多线程...

    1 关于volitate关键字,描述不正确的是()
    A 用volitate 修饰的变量, 每一次的更新对其他的线程都是可见的;
    B 对volitate 的操作是原子性的
    C 对volitate 的操作不会造成阻塞
    D 不依赖其他的锁机制,多线程环境下的技数器可以用volitate 来实现
    注解: 一旦一个共享变量(类的成员变量,类的静态成员变量)被volitate修饰,那么,其就具备了两层含义:
    1) 保证了不同的线程对这个变量进行操作的时候的可见性;即一个线程修改了某个变量, 这个新的值对于其他的线程来说是立即
    可见的。
    2) 禁止进行指令的重排序(volatile关键字能确保变量在线程中的操作不会被重排序而是按照代码中规定的顺序进行访问)
    volatile 只提供了保证访问该变量,每一次读取改变量的时候都是从内存中读取,并不会使用寄存器缓存该值.
    对该变量的修改,volatile 并不提供原子性的保证;
    由于及时更新,volitate 可能导致另一线程访问最新变量值,无法跳出循环的情况,
    多线程下,计数器必须使用保护锁;
    *注:原子性解释1:原子性就是说一个操作不可以被中途cpu暂停然后调度, 即不能被中断, 要不就执行完, 要不就不执行. 如果一个操作是原子性的,那么在多线程环境下, 就不会出现变量被修改等奇怪的问题。
    原子性解释2:原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。Java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。

    展开全文
  • 本书是一本关于Java最佳实践集大成之作,它从Java语言本身、Java程序架构设计和思想、Java程序编码规范和习惯等方面对151个经典问题给出了解决方案,为Java开发者提高开发效率和编写高质量Java代码提供了...
  • volatile关键字 一、一旦一个共享变量(类的成员变量,类的静态变量)被volatile修饰之后,那么就具备了两层语义;...题目:关于volatile关键字,下列描述正确的是? A、用volatile修饰的变量,每次更新对
  • 真正侯捷《深入浅出mfc》chm版

    热门讨论 2010-05-05 22:08:42
    静态成员(变量与函数) /44 C++程序生与死:兼谈构造函数与析构函数 /46 四种不同对象生存方式 /47 所谓“Unwinding”/48 运行时类型信息(RTTI) /48 动态生成(Dynamic Creation) /50 异常处理...
  • 2.运行Qt Creator,首先弹出的是欢迎界面,这里可以打开其自带的各种演示 程序。 3.我们用File->New 菜单来新建工程。 4.这里我们选择Qt4 Gui Application。 5.下面输入工程名和要保存到的文件夹路径。我们这里的...
  • 熟悉后再一个函数一个函数地深入学习exosip提供接口函数,就可以深入理解osip 了,达到间接学习oSIP目的,同时也能从eXoSIP中学习到正确使用oSIP良好编程风格和语法格式。 而要成功编译...
  • 你必须知道495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    1.10 对于没有初始化的变量的初始值可以作怎样的假定?如果一个全 局变量初始值为“零”, 它可否作为空指针或浮点零? . . . . . . . 4 1.11 代码int f() f char a[] = "Hello, world!";g 不能编译。. . . . . . . 5...
  • 6 以下关于内存管理描述错误的是:( )A、基本数据类型的变量、对象的引用及函数调用的现场保存都使用内存栈空间B、通过new关键字和构造器创建的对象放在堆空间,类信息、常量、静态变量放在方法区C、计数器是唯...
  • 3.7.2 模式结构的正确命名 53 3.7.3 ER概念设计设计选择 54 3.7.4 ER图候选表示法 55 3.8 其他表示法示例:UML类图 55 3.9 高于2度联系类型 57 3.9.1 对二元和三元(或高度)联系选择 ...
  • 它和所在的外部类的任何实例无关它可以访问所在方法中声明为final的变量它可以被任何一种访问修饰符修饰它不能实现接口答案:AB2、请问以下关于静态内部类的说法正确的是?它必须实现一个接口它可以被其他类访问它...
  • 编译原理之语义分析

    千次阅读 2020-04-07 15:16:13
    和语法不同,语法是关于程序及其组成部分的构成规则的描述,是上下文无关的;而语义是关于语法结构的含义及其使用规则的描述,是上下文有关的。 语法上正确,其语义不一定正确。语义分析与中间代码生成器基于语义...
  • 对象声明描述的是存 储在对象中的信息以及可对对象执行的操作(类方法)。对象的某些组成部分对于外界来说是可见的(公有部 分),而某些部分却是隐藏的(私有部分)。特殊的类方法(构造函数和析构函数)在对象创建和释放...
  • 下列关于虚函数的描述,不正确的是( ) a.全局变量在任何函数体内都有效 b.不能将析构函数说明为虚函数 c.虚函数不能是静态的成员函数 d.为了实现多态性,派生类必须重新定义基类的虚函数 这道选择题怎么做,求...
  • 对象声明描述的是存 储在对象中的信息以及可对对象执行的操作(类方法)。对象的某些组成部分对于外界来说是可见的(公有部 分),而某些部分却是隐藏的(私有部分)。特殊的类方法(构造函数和析构函数)在对象创建和释放...
  • 对象声明描述的是存 储在对象中的信息以及可对对象执行的操作(类方法)。对象的某些组成部分对于外界来说是可见的(公有部 分),而某些部分却是隐藏的(私有部分)。特殊的类方法(构造函数和析构函数)在对象创建和释放...
  • 对象声明描述的是存 储在对象中的信息以及可对对象执行的操作(类方法)。对象的某些组成部分对于外界来说是可见的(公有部 分),而某些部分却是隐藏的(私有部分)。特殊的类方法(构造函数和析构函数)在对象创建和释放...

空空如也

空空如也

1 2 3 4 5 6
收藏数 112
精华内容 44
关键字:

关于静态变量的描述正确的是