JAVA基础 止8月30日
java中==和equals和hashCode的区别
==是比较内存地址是否一致,equals是Object默认的方法它的实现是比较对象是否相等,也就是比较的内存地址。String有重写equals方法,它的内部操作是比较内存地址中的值是否一致。
String str = new String("abc");
String str1 = new String("abc");
str==str1 false
str.equals(str1) true
- hashCode
hashCode是Object中默认的一个方法,如果不是想这个方法那么,它就是返回对象在JVM中的32位内存地址。
hashCode的作用是代表对象的一个唯一标识,解决那种在对象很多的情况下查找某个对象,快速定位对象地址问题。就是相当于对象的一个指纹,作用于hash算法中。
单精度和双精度
单精度即float,在计算机中占用四个字节,32位有效位数7位。 双精度 double,占用8字节 64位有效位数16位,64位浮点数就是双精度。
java8中基本数据类型
整型
int a = 10;
byte a1 = 10;
long a2 = 10;
short a3 = 10;
浮点类型
float a4 = 11;
double a5 = 11.2;
字符类型
char a6 = 6;
逻辑型
boolean a7 = false;
int、char、long各占多少字节数
int=4个字节 char=2个字节 long=8个字节
int与integer的区别
int是java中的基本数据类类型,Integer是一个对象int的包装类,也可以叫做被装过箱的类。
Integer是对象比Int要暂用过多的内存空间
这种方式都是存储在常量池
int a = 10;
Integer =10;
通过new创建存储在堆内存中
Integer age = new Integer(10)
Integer age1 = new Integer(10)
Integer age2 = new Integer(10)
age1==age2 false
int age1= 10;
Integer age2 = 10;
true
int age = 10;
Integer age2 = new Integer(10);
true 原始类型和包装类比较时,包装类型会自动转成int。这个时候比较的是值了所以会是ture.
Integer age =10;
Integer age1= new Integer(10);
age == age1
false 一个是在常量池,一个是在堆内存。不一样的内存地址所以是false
java封装继承多态
-
封装
封装就是把类的属性和方法的具体实现细节隐藏起来,对外暴露公开的访问方法 。 目的增强安全性和简化编程,调用者不需要关系具体的实现细节,通过new对象就可以很便捷的使用类的成员和方法。 -
继承
在java中继承可以说是无处不在,我们每写的一个类都默认有一个继承关系,继承一个Object的父类。继承关系是可以在原来类的基础上,增加新方法重新方法,从而产生一个新的类。
子类无法访问父类中的private修饰的成员,可以重写父类的公开方法和成员。
- Java三种类划分
- 普通类
- 抽象类
- 接口
-
继承规则是
普通类可以extends普通类,可以extends抽象类,可以implements接口。
抽象类可以extends普通类,可以extends抽象类,可以implements接口。
接口只能implements接口 -
优点
通过继承我们可以扩展一个类的功能,扩展的子类之间互相不影响,如果有需要增加方法,我们只需要在扩展一个子类,继承可以让一个类在不影响现有的情况下,实现一个增量的操作,通过重写和复用,大大提高了开发效率,而且不需要对原来的类进行测试。 -
多态
相同的类,调用相同方法,参数相同,但表现的行为却不一样。
类多态
继承是多态得以实现的基础,不同的子类继承一个父类,这些子类重写父类的方法,每个子类的实现都是不一样的。
接口多态
不同类实现同一套接口,每个类的实现细节都是不一样,运行时期,动态判断类型。调用不同类的实现方法。
好处
多态就是消除之间的耦合,使程序更容易扩展。相同的事物可以有多种表现的形态。
-
重载
在一个类中定义了一个相同的方法,但是方法的型构不一样。 -
重写
重载就是多态的一种具体的表现,子类重写父类中一模一样的方法。
String、StringBuffer、StringBuilder区别
String
是java中的一种基本数据类型,这个类是被final修饰所以值是不可变的,类也不能被继承。每次修改都会产生一个新的对象。
创建string三种方法
-
String str = new String("abc")
new关键字创建的对象存储在堆内存 -
String str1 = "abc"
直接赋值的直接指向常量池 -
String str = "abc"+"d"
+拼接的方式,也是指向产量池 -
String str = "abc"+str1
这种会直接指向堆内存,编译器会在编译时通过StringBuder拼接这种通过变量拼接的字符串
StringBuilder
是一个字符串的拼接类,可以通过append方法对字符实现变更拼接而不会导致创建多个对象,他是线程不安全的。
StringBuffer
和StringBuilder一样也是一个拼接字符串的类,但是它都线程安全的,方法上面都加入了同步关键字,安全性比较高,但是效率低。
如果需要进行多次拼接操作,就需要使用StringBuilder和StringBuilder来提高效率。
抽象类和接口区别
抽象类与接口的应用场景
抽象类一般作用域顶级基类,一个包含抽象方法的类,类也必须是抽象的。子类如果继承于抽象类必须实现抽象类的方法。如果我们的类中的某些方法必须由子类去实现,那么我们就可以用抽象去修饰这个类和方法,然后我们就可以在父类中去处理这些叫由子类实现的方法。它不能被实例化,只能被用作子类的超类。
Java中一个类可以实现多个接口。接口的出现可以让我们不需要关系接口内部的具体实现,调用这只要持有这个接口就能调用。如果需要扩展更多的功能我们只需要扩展实现这个接口的类,不会影响到之前的实现类。
抽象类是否可以没有方法和属性?
可以
接口的意义
接口也是多态的一种,由于在Java中实现的是单继承规则,所以导致,如何我们需要扩展类更多的属性时,单继承有了一定限制。接口可以解决这个问题,Java中一个类可以实现多个接口。接口的出现可以让我们不需要关系接口内部的具体实现,调用这只要持有这个接口就能调用。如果需要扩展更多的功能我们只需要扩展实现这个接口的类,不会影响到之前的实现类。
泛型中extends和super的区别
使用extends的泛型叫上限通配符,泛型只能接收extends这个类及以下的类。
使用super的泛型叫下限通配符,它的范围是只能接收这个类或者它的超类。
进程和线程的区别
进程指运行过程中的程序,进程是系统进行资源分配的一个单位,它具有独立性有独立的空间地址,进行拥有自己的生命周期执行、就绪、等待。线程是包含在进程之内的是程序最小的执行单元,一个进程可以拥有多个线程。
final,finally,finalize的区别
final是java的一个修饰符用户修饰变量、方法、类等不可以被重写和改变。 finally是java异常处理的部分,用于try语句后那些必须执行的代码,就可以放入到这个代码块中。
finalize是object类的一个方法,JVM进行GC操作的时候会调用这个方法。
序列化的方式
Serializable 和Parcelable 的区别
Serializable是JAVA中提供的系列化接口,在需要实现的类中实现接口,实现它后自动会做序列化操作。这种方式的缺点是
使用的反射序列化过程比较慢,在序列化过程会创建很多临时变量,容易触发GC。
Parcelable 速度快是android自己提供的序列化接口。据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化
静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
可以被继承
原因:静态变量是和Class一起初始化的,所以类都能通过类名使用它,既然这样子类当然也可以直接使用了,继承不继承都是一样的。
不能被重写
原因:我们重新父类的静态修饰,编译器虽然不会阻止我们这么做,但是不能得到预期的结果。重写是指根据运行时的结果来确定类型,而静态修饰的方法成员是编译时就确定好的,因为它们会随着类而加载。
- 子类可以基础父类的static变量或者方法
下面这个类继承了A类,打印的时候可以直接引用父类的属性和方法,证明static是能被继承的。
public class ClassA {
public static String name1 = "A类静态属性";
public String name2 = "A类非静态属性";
public static void getName1() {
System.out.println("A类静态方法");
}
public void getName2() {
System.out.println("A类非静态方法");
}
}
public class ClassB extends ClassA {
}
public class MainClass4 {
public static void main(String[] args) {
ClassB b = new ClassB();
System.out.println(b.name1);
System.out.println(b.name2);
b.getName1();
b.getName2();
}
}
打印-》A类静态属性
打印-》A类非静态属性
打印-》A类静态方法
打印-》A类非静态方法
- 父类的static成员和方法不能被重写
下面可以看到C类的成员和方法和父类一样,但是调用的时候都是调用的父类的方法,证明调用的是声明类的静态属性和方法,没有实现子类重写。
public class ClassC extends ClassA {
public static String name1 = "C类静态属性";
public String name2 = "C类非静态属性";
public static void getName1() {
System.out.println("C类静态方法");
}
@Override
public void getName2() {
System.out.println("C类非静态方法");
}
}
public class MainClass4 {
public static void main(String[] args) {
ClassA c = new ClassC();
System.out.println("--------");
System.out.println(c.name1);
System.out.println(c.name2);
c.getName1();
c.getName2();
}
}
打印->C类静态属性
打印->C类非静态属性
打印->C类静态方法
打印->C类非静态方法
静态内部类的设计意图
静态内部类的访问不依靠外部类,它的加载机制和普通静态内部类一样会在编译时期被加载,它的访问限制是不能访问外部类中非static修饰的成员。所以有时候如果我们需要自己的内不想依靠外部类的初始化,或者使用便捷就可以考虑用static修饰内部类。
成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及项目中的应用
什么是内部类?
内部类就是在一个类中定义一个类叫内部类,在JAVA中实行的是单继承的规则,如果实行多继承的话,会导致一些概念被混淆。比如二个父类的有相同的成员变量和属性是相同的,那么子类到底是使用哪个。所以多继承会导致这些逻辑上的问题,不符合面向对象的原装。
但是我们可以通过实现多接口的形式来扩展父类不能解决的问题,内部类就也可以更好的扩展,它可以继承其他的父类和外部类不一样的父类,也可以扩展多个接口实现。并且不受外部类的影响。
- 几种内部类
- 成员内部类
它的存在必须依靠外部类才能存在是典型的内部,它可以访问外部类的成员和函数,因此它持有外部类的因引用,如果外部类要访问它必须先创建外部类,或者返回内部的实例给外部。
public class Class1 {
void mode() {
}
public class Class5 {
}
}
- 局部内部类
局部内部类是定义在一个方法或者一个作用域里面得类,局部内部类的访问权限只限于方法内或者该作用域内,如果访问外部类的成员变量,需要final修饰,这种设计意图是有的时候代码块不想被外部访问,只作用于方法体内的作用域。
@Test
public void addition_isCorrect() {
final int age = 10;
class Class2 {
int b = age;
}
}
- 静态内部类
静态内部类,静态内部类无法访问外部内的成员变量或者方法,所以它没有持有外部类的引用,我们可以直接不初始化外部类的情况下使用这个静态内部类。
static class Class2 {
}
- 匿名内部类
匿名内部类是唯一一种没有构造器得类,匿名内部类就是没有类名的类,它写法比较简洁,匿名内部类访问外部成员也需要final修饰。
final int age = 10;
new Thread() {
int a = age;
};
谈谈对kotlin的理解
参考资料
kotlin是一门基于JVM虚拟机的静态类型编程语言(静态类型就是在编译时期就确定了类型,如有错误编译无法通过。 动态类型编译时期没确定类型,可能回到运行时期出现错误。)2011年推出的项目,它的主要一些特性有。
- 类型推断
- 多平台,可以在android 浏览器
- 在编译前期检查Null异常,解决运行时出现的nullI异常。
- 语法比较简介lambda表达式,高阶函数,扩展函数,运算符重载。 ...等
- android官方的推荐语言
- 能够和JAVA 100%的融合执行。
- Anko直接使用xml中的控件ID,省去findById
闭包和局部内部类的区别?
闭包是把一个类的内部类通过函数的形式创建出来,提供给外部类使用,外部内不知道具体实现细节。局部内部类是内部类的一种实现方式,它定于于方法体内或作用域内,它相对于其他内部类而言,它的访问权限只限于它的方法或者作用域范围,而且被访问成员需要用final修饰。
为什么局部和匿名内部类访问的变量需要被final?
比如在一个方法体中定义了一个局部类,这个时候有可能方法执行完毕之后它的局部变量也会消失掉,如果内部类中的代码还没完成。如果不被final修饰的话,那么它访问的就是一个消失的成员,所以用final修饰后它就成员一个常量,不会影响到内部类中未完成执行的代码。
- 闭包
定义一个闭包的要点如下:
- 一个依赖于外部环境的自由变量的函数.
- 这个函数能够访问外部环境的自由变量.
- 闭包就是用一个类把另一个类包装起来,对外不暴露实现细节,闭包的具体实现就是内部类。
string 转换成 integer的方式及原理
(一)图片
图片库对比
图片库的源码分析
图片框架缓存实现
LRUCache原理
图片加载原理
自己去实现图片库,怎么做?
Glide源码解析
Glide使用什么缓存?
Glide内存缓存如何控制大小?
大图优化?
网友评论