笔记(一 )——Java零碎知识摘录

2019-10-11  本文已影响0人  木溪bo

——》个人平时笔记,看到的同学欢迎指正错误,文中多处摘录于各大博主精华、书籍

1、android:exported属性:主要作用是:是否支持其它应用调用当前组件。默认值:如果包含有intent-filter 默认值为true; 没有intent-filter则默认值为false。虽然说加了这个属性,可以使该组件不被其他的程序调用。但是,需要注意的是,如果两个程序的userid是一样的话,exported=”false”会失效。

2、 java反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。即:java在运行状态中反射知道一个类里面的所有方法和属性;通过反射获得对象后,能够调用对象的任意属性和方法。

java内省:内省基于反射实现,主要用于操作JavaBean,通过内省 可以获取bean的getter/setter,只要看到有getter或者setter就认为这个类有那么一个字段,比如看到getName() 内省就会认为这个类中有name字段,但事实上并不一定会有name。

image

3、泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。参数化类型就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参),由传入的实参类型决定的参数类型。在方法中使用通配符“?”作为形参,实则它的使用是一种类型实参,此时“?”可以理解为说有类型实例的父类,就是一种真实的类型。
java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一

public void showKeyValue1(Generic<?> obj){
 
     Log.d("泛型测试","key value is " + obj.getKey());
 
 }
image
4、 泛型通配符“?”(泛型详解)

“ ? ”是通配符,泛指所有类型:一般用于定义一个引用变量,这么做的好处是,如下所示,定义一个sup的引用变量,就可以指向多个对象。

 SuperClass<?> sup = new SuperClass<String>("lisi");

       sup = new SuperClass<People>(new People());
 
       sup = new SuperClass<Animal>(new Animal());
 
 若不用?,用固定的类型的话,则:
> 
> SuperClass<String> sup1 = new SuperClass<String>("lisi");
> 
> SuperClass<People> sup2 = new SuperClass<People>("lisi");
> 
> SuperClass<Animal> sup3 = new SuperClass<Animal>("lisi");

这就是?通配符的好处。

? extends T, ?是指T类型或T的子类型

? super T ,?是指T类型或T的父类型

这个两个一般也是和?一样用在定义引用变量中,但是传值范围不一样

T和?运用的地方有点不同,?是定义在引用变量上,T是类上或方法上;如果有泛型方法和非泛型方法,都满足条件,会执行非泛型方法。

带不同泛型的ArrayList在编译后生成的Class是相同的!也就是说,泛型在编译生成字节码文件时会被”擦除”;不管ArrayList<E>带什么泛型,在编译后都是ArrayList所对应的字节码文件。

eg:

image

5、Java 如何有效地避免OOM:善于利用软引用和弱引用

强引用:直接的对象引用,实例化对象。在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象。中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。在方法内部有一个强引用,这个引用保存在 java栈 中,而真正的引用内容 (Object)保存在 java 堆中。当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为 0 ,这个对象会被回收。

软引用:有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。当一个对象只有软引用存在时,系统内存不足时此对象会被JVM回收。一般用于服务端。

弱引用:弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。只要JVM进行垃圾回收,被弱引用关联的对象必定会被回收掉。移动端内存紧缺推荐使用弱引用。

虚引用:虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收

在使用软引用和弱引用的时候,我们可以显示地通过System.gc()来通知JVM进行垃圾回收,但是要注意的是,虽然发出了通知,JVM不一定会立刻执行,也就是说这句是无法确保此时JVM一定会进行垃圾回收的。

6、try catch是直接处理,处理完成之后程序继续往下执行;throw则是将异常抛给它的上一级处理(是明确的一定会抛出异常),程序便不往下执行了。

throws并不是抛出一个实际的Exception而是一个异常声明,它声明这个方法可能会抛出一个异常,注意是可能,所以在没有异常的情况下也是可以用throws的,而throws本身的作用也是用来提高程序的健壮性,反过来,如果这个方法的的确确的有一个异常,那么编译器会强制让你加上throws这个异常声明。

try这个程序块名字很易懂,就是尝试,尝试能不能正常的走完整个作用域,所以我们在try块里经常放上可能会抛出异常的程序段。而catch恰好就是处理try里抛出来的异常,其中catch的参数列表接收的是一个异常的引用,是throw抛出来的异常的引用,这样我们就可以得到这个异常的对象,倒不如说我们是得到了这个异常对象的引用,因为在java里,通常我们也只能通过引用来操纵对象。

7、一个类只能初始化一次,却可以多次实例化。java虚拟机类加载机制

类的初始化的执行顺序

》没有父类的情况:

类的静态属性

类的静态代码块

类的非静态属性

类的非静态代码块

构造方法

》有父类的情况:

父类的静态属性

父类的静态代码块

子类的静态属性

子类的静态代码块

父类的非静态属性

父类的非静态代码块

父类构造方法

子类非静态属性

子类非静态代码块

子类构造方法

部分特殊不引起类初始化,先记录下吧。

通过子类引用父类的静态字段,不会导致子类初始化,对于静态字段,只有直接定义这个字段的类才会被初始化

通过数组定义来引用类,不会触发此类的初始化

常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类初始化

public static final int x =6/3; 能够在编译时期确定的,叫做编译常量,不会引起类的初始化!!!

public static final int x =new Random().nextInt(100); 运行时才能确定下来的,叫做运行时常量,运行时常量会引起类的初始化!!!,类的初始化只会有一次

在虚拟机规范中使用了一个很强烈的限定语:“有且仅有”,这5种场景中的行为称为对类进行主动引用。除此之外,所有引用类的方式都不会触发初始化,称为被动引用。

8、字符串在Java生产开发中的使用频率是非常高的,字符串对于我们而言非常关键。在C中是没有String类型的,那么C语言要想实现字符串就必须使用char数组,通过一个个的字符来组拼成字符串。而在Java中String源码分析可知,String也是char数组拼接而成的。字符串一定会被保存到常量池中,且Java虚拟机如果发现常量池中已经存在需要创建的字符串中,它就不会重复创建,而是指向那个字符串即可,(深入Java源码剖析之字符串常量)这就类似于如下操作。

 Student aa=new Student(123,"小花");//保存在堆内存中,而非常量池
 Student bb=aa;
 Student cc=aa;

9、Java中的 数据类型分两种:基本数据类型和引用数据类型
基本数据类型:Java中的简单类型(基本数据类型)从概念上分为四种:实数、整数、字符、布尔值。八种基本数据类型如下:

实数:double、float
整数:byte、short、int、long
字符:char
布尔值:boolean

复杂类型(引用数据类型):String、类对象、数组。

引用数据类型和基本数据类型的内存模型本质上是不一样的。
基本数据类型的存储原理是这样的:所有的基本数据类型不存在“引用”的概念,基本数据类型都是直接存储在栈内存中的,栈空间里存储的地址就是数据本身的值。而Java语言里面只有这八种基本数据类型是这种存储模型;

而其他的只要是继承于Object类的引用数据类型,都是按照Java里面存储对象的内存模型来进行数据存储的。引用数据类型使用Java内存堆和内存栈来进行这种类型的数据存储;堆内存存储值,栈中存储对象在堆内存的首地址(引用地址),而这个栈引用就叫引用变量。

简单地讲,基本数据类型是存储在有序的栈内存中的,而引用数据类型本身的值存储在堆内存中的。

基本数据类型由于长度固定,且需要空间比较少,所以直接存储在栈中;而对象比较大,所以栈中只存储一个4btye大小的引用地址,堆内存中存值。

10、java中声明了一个变量,便会给这个变量分配内存空间,且被声明的变量会对应有一个内存地址生成。在类型转换中,低比特数(bit)的数据类型向高比特数的类型转换可以自动转换,高比特数的数据类型向低比特数的类型转换就需要使用强制类型转换了。

比特数由低到高 byte->short->char->int->long->float->double

1.bit就是位,也叫比特位, 也是b ,是计算机表示数据最小的单位

2.byte就是字节,也是B

3.1byte=8bit

4.1byte就是1B

5.一个字符=2字节

6.1KB=1024B

7.转换关系如下:

(1)1KB=1024B

(2) 1B= 8b

11、栈内存、堆内存、常量池区别:

Java内存分配主要包括以下几个区域:

  1. 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制
  1. 栈:存放基本数据类型的数据和对象的引用(引用变量),但对象本身不存放在栈中,而是存放在堆中
  1. 堆:存放用new产生的数据或者说对象
  1. 静态域:存放在对象中用static定义的静态成员
  1. 常量池:存放常量。字符串常量(例如:String a="123")和final修饰的基本数据类型常量。
  1. 非RAM(随机存取存储器)存储:硬盘等永久存储空间
字符串
 由上图可以看出,使用双引号直接定义的String对象会指向常量池中的同一个对象,通过new产生一个字符串(假设为“china”)时,会先去常量池中查找是否已经有了“china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象

----》好文参考推荐:Java内存分配之堆、栈和常量池

修饰符作用域
12、静态变量、静态方法是不属于某个实例对象,而是属于类的,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。每个静态变量内存地址是唯一的,UserBean类中有一个name静态变量,不管new UserBean()多少个实例,name变量所指向的内存地址是唯一的(也就是说m1.name、m2.name和UserBean.name指向同一个变量),只要有一个地方对静态变量做更改,所有使用引用的地方都会改变,eg:m1.name=“小红”,则m2.name、UserBean.name都是改为了“小红”。

静态初始化器:静态初始化器是类中由static修饰的一对“{ }”包裹的,不同于构造方法,它并不是方法,因为它并没有返回值和方法名。它是属于类的,在初始化器加载类的时候初始化一次,其它时候不执行不加载。多个静态初始化器是按编码秩序依次执行。

注意:静态内部类默认持有外部类实例引用, 而导致外部类无法释放,最终造成内存泄露。这时候就要给外部实例引用添加弱引用标识符了,尽可能的避免泄漏。

是否可以从一个static方法内部发出对非static方法的调用?

不可以。因为非static方法要与对象关联在一起,必须创建一个对象后,才可以在该对象上进行方法的调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,一个static方法被调用时,可能还没有创建任何实例对象,所以,一个static方法内部不可以发出对非static方法的调用。

13、Java中是值传递,而不是引用传递,不管是是基本数据类型还是引用数据类型都是值传递。
java参数传递(到底是值传递还是引用传递?)
java是值传递还是引用传递?

14、List 接口实现了 Collection 接口,它主要有两个实现类:ArrayList 类和 LinkedList 类。

List:有序集合
Set:不重复集合,LinkedHashSet按照插入排序,SortedSet可排序,HashSet无序
Map:键值对集合

15、Map的几种类型

HashMap可以使用可变对象作为key,但是对象实体类需要重写equals(Object obj)、hashCode()两方法

map.jpeg

16、String,StringBuffer与StringBuilder的区别

17、Java中类、抽象类、接口:

上一篇 下一篇

猜你喜欢

热点阅读