201709013工作日记--static理解 && abstract

时间:2021-12-20 19:30:49

1.关于viewHolder设置成static的讨论

一般情况下是尽量不要使用static关键字,因为static一旦有引用变量指向了变量,使用完毕后而没有设置null,就会造成内存泄露,而且很难排查。但并非绝对不允许使用static,你需要非常小心的维护这个static的引用。

这里要讨论的是在listView优化时,使用的viewHolder,这个类Google的示例程序将该类定义为静态内部类,是因为它没有依赖任何外部类,它本身是独立的,不会存在内存泄漏。更为详细的解释如下:

(1)一般来说,我们声明为静态嵌套类,当它没有依赖外部类。在我们的例子中,ViewHolder类从未引用(访问)适配器类的任何成员变量(外部类),因此我们可以声明为静态的。保持简单nested-static类只是另一个(外)类是嵌套的可读性,因为它的使用仅限于只有它的外部类。你必须宣布非静态嵌套类(称为内部类)如果访问外部类的成员变量。

(2)《Effective Java》第22条 优先考虑静态成员类 其中有条建议: 如果声明成员类不要求访问外围实例,就要始终把static修饰符放在它的声明中,使它成为静态成员类,而不是非静态成员类。 因为非静态成员类的实例会包含一个额外的指向外围对象的引用,保存这份引用要消耗时间和空间,并且导致外围类实例符合垃圾回收时仍然被保留。如果没有外围实例的情况下,也需要分配实例,就不能使用非静态成员类,因为非静态成员类的实例必须要有一个外围实例。

PS:强烈推荐《Effective Java》这本书,会让你有意想不到的收获。http://www.jianshu.com/p/be247a4cf359

(3)这篇文章中没有提到加载时机的问题吧。在我的理解中:静态内部类主要作用就是,内部类是否需要隔离“外部类的this对象(指针)”。内部类是有 this 指针的,可以“直接”访问外部类的 成员变量和成员函数(包括私有的成员)。而静态内部类,没有这个this指针,所以无法“直接”调用。  Android代码中,经常使用的Builder,LayoutParams都是以静态内部类的方式存在啊。我们可以根据实际使用情况来效仿。  对于这篇文章,我理解。ViewHolder的构造和复用,与静不静态没关。核心是ListView(AdapterView),通过getView(int position, View convertView, ViewGroup parent) 的convertView会为开发者传入一个可以复用的对象。开发者需要利用该对象,减少应用内存的消耗。 如果从减少内存消耗的角度来开。我认为ViewHolder还是应该修饰成static比较好。这样ViewHolder中可以减少MainActivity的this指针,由于减少了一个this指针的引用,也会对MainActivity的引用计数大大减少。MainActivity的this指针继承于android的Context上下文,对于Context的回收遗漏,是Android内存管理中很大的问题。我们减少了对Context的引用,可以更容易减少Context引用计数出现问题。

(4)*相关解答:https://*.com/questions/13516835/why-in-viewholder-pattern-should-the-viewholder-class-be-static

2. java为什么会有静态抽象类?继承静态(内部)抽象类时发生了什么?

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild
{
.......
public static abstract class ViewHolder {...}
......
}

静态内部类和定义一个普通的类没啥区别,只不过静态内部类是定义在另一个类内部了。   继承内部静态抽象类,也没啥特别的事发生。

首先 static 只能用来修饰类的成员,所以*类不能用 static 修饰。

所以 static class 一定是一个内部类,即静态内部类。

静态内部类与外部类之间并没有任何关系,其外部类仅仅起到一个名字空间的作用,和包名起差不多的作用。而静态内部类也不持有外部类的引用,也不能引用外部类的private成员。  一个静态内部类其实是具有*类的地位,那么和一般的抽象类其实并没有什么不同。

3. java中抽象类为什么不能定义为static型?

一般分两个阶段

阶段一:先载入类

阶段二:然后才能依据类来实例化对象 而static的方法、变量都是属于类的,非static的则属于对象

如果在阶段一,访问非static的方法,因为还没有对象,所以不能访问成功

如果在阶段二,一个类有那么多对象在内存生存着,类也不知道该访问哪个对象的实例变量

4. 外部抽象类不能用static修饰

static的用法:
  1、static 关键字:可以用于修饰属性,也可以用于修饰方法,还可以用于修饰类。
  2、static 修饰属性:无论一个类生成了多少个对象,所有这些对象共同使用唯一一份静态的成员变量;一个对象对该静态成员变量进行了修改,其他对象的该静态成员变量的值也会随之发生变化。如果一个成员变量是static 的,那么我们可以通过 类名 .成员变量名 成员变量名 成员变量名 的方式来使用它 的方式来使用它 (推荐使用这种方式) 。
  3、static修饰方法: static 修饰的方法叫做静态。 对于静态方法来说,可以 使用 类名 .方法名的方式来访问。
  4、静态方法只能继承,不重写(Override)
  5、不能在静态方法中访问非静态成员变量;
  6、不能在静态方法中使用this关键字。

7、静态内部类是可以用static修饰的

5.不可以和抽象abstract关键字共存的关键字

1).private :因为一个abstract方法需要被重写,所以不能修饰为private;

 2).final:因为一个abstract方法需要被重写。被final修饰的方法是不能被重写的,所以不能同final共存;
 3).static:因为一个abstract方法没有方法体。静态方法需要对方法体执行内容分配空间,所以不能同static共存;(abstract是没有实现的,不能产生对象,而是static是属于类的,类本身是已经存在的对象)
 4).synchronized: 是同步的,然而同步需要具体的操作才能同步,但, abstract是只有声明没有实现的(即,使用synchronized关键字的是需要有具体的实现同步的操作的,但是使用abstract是只有声明而没有实现的,这样就产生了冲突)
 5).native:他们本身的定义就是冲突的,native声明的方法是移交本地操作系统实现的,而abstract是移交子类对象实现的,同时修饰的话,导致不知道谁实现声明的方法