面向过程:面向过程的性能比面向对象的性能高(参考C与Java的区别)。
面向对象:代码可读性高,容易维护,容易扩展。
- 多态
- 封装
- 面向对象
- 线程安全
- 网络编程比较方便(面向业务端)
- 可靠性
- 安全性
- 编译与解释共存
在我的视角JVM就是帮助实现跨平台的,Java的字节码虚拟机
JDK是开发者工具,拥有JRE拥有的一切
JRE是Java的运行环境
- 面向对象
- Java没有指针,C++有指针,相对来说说Java安全性更高(带来的性能也就低了一些)
- Java单继承,C++是多继承的,Java是通过接口这个东西变相实现了多继承。
- Java不需要程序员手动释放内存
- 字符串结尾有区别
- 字符常量代表一个字符,而字符串常量代表多个字符
- 占据内存大小不一样
- 一个是数值类型的,一个是表明一个地址
构造器不能被重写
重载和重写的区别重写是发生在继承上面的,是子类重写父类同名,同变量的方法,返回类型也要相同,而且抛出异常的范围要小于父类
重载发生同一个类上,同名不同变量的方法
封装,典型的就是Private,限定能够访问的等级,防止乱修改
继承,在原有类的基础上增加或者改变一些功能或者方法,核心目的还是为了复用以前的代码
- 子类拥有父类对象的所有属性和方法,但是私有属性是无法访问的
- 子类可以用自己的方法实现父类的方法
- 子类可以拥有自己的属性和方法
多态,在程序运行的时候才会确定调用哪个类比如 Animal = Cat() Animal.eat(),可以通过继承或者接口来实现这个功能。
- String类中使用final关键字修饰字符串数组来保存字符串,所以String是不可变的,他是被final修饰的。
- StringBuffer和StringBuilder都是继承AbstractStringBuilder,所以这两个是可以改变的,并没有被final关键字修饰
- StringBuilder是StringBuffer的县城不安全版本,可以提高性能,但是不值得。
- 装箱:将基本类型用它们对应的引用类型包装起来
- 拆箱:将引用类型转换成基本类型
因为这个成员有可能还没有被初始化。
Java中定义一个不做事且没有参数的构造方法加上这个方法主要防止子类因为没有使用super()关键字重写父类的构造方法而造成的编译错误
接口和抽象类的区别是什么- 接口中除了static final不能有其他变量
- 接口抽象的是行为,而抽象类抽象的是对象
- 接口的方法默认是public,方法不能在接口中实现
- 对象可以实现多个接口只能继承一个抽象类
- 生存周期不同
- 局部变量不能被static修饰
- 成员变量会被附上初始值,而局部变量不会
- 存储方式不同。如果局部不变量是基本类型放在栈中,如果是引用类型放在堆中
返回方法执行的后果,他的通就是接受结果,使得这个方法的结果可以被其他方法使用
类的构造方法用于初始化这个对象,没有写构造方法会自动带一个无参的构造方法。
构造方法特性1.没有返回值
2.与类同名
3.生成对象的时候自动调用。
4.调用子类构造方法之前会调用父类构造方法,帮助类完成初始化。
1.静态方法可以通过类名调用实例需要初始化对象之后才能调用
2.静态方法不能访问成员变量
对象相等是内存中存放的内容是否相等, 而引用相等,是地址是否相等。简单来说对象相等,就是两个存放的东西一不一样,引用相等就是地址是否相等。
== 和 equals的不同- == ,对于基本类型比较的是值,对于引用类型表示的是地址是否相等
- equal表示的是对象是否相等,如果没有重写euqals方法,就是等价于==,如果重写了euqal方法一般来说会根据对象中的值是否相等来返回True or False
在使用HashSet来装载对象的时候,首先会拿HashCode来进行比较,如果没有相同的HashCode就认为这个对象并没有在集合中出现过。如果出现了相同的HashCode就会拿equals来比较,如果equals结果为False会散列到其他位置,equals相等,就拥有相同的HashCode,如果equals不等,则HashCode不等。简单来说HashCode是euqals相等的必要不充分条件,糟糕的散列算法会使得HashCode碰撞概率提升。
线程 程序 和进程线程是比进程更小的单位,进程可以产生多个线程。同一个进程产生的线程共享内存cpu等资源。在线程级别的切换代价小很多。
程序是一个完整的指令,包含数据和指令,存储在设备程序。
进程是程序的一次执行过程。
- 创建状态
- 运行状态
- 阻塞状态
- 等待状态
- 终止状态
- final修饰变量,则这个变量不能更改。如果修饰的是一个引用变量,则这个变量之后就不能指向其他对象。
- 当final修饰一个雷, ,表示这个类不能被继承,
- final修饰方法,子类不能重写这个方法
java中有字节流和字符流,字符流是java虚拟机将字节转换得到的,比较耗时且会出现乱码的问题,所以提供一个字符流,直接 *** 作字符。但是对于一些音频,图片视频等文件,直接用字节流比较好。
深拷贝和浅拷贝深拷贝,相当于创建一个对象,然后赋予相同的值
浅拷贝,复制一个地址
List普通集合,可以由重复元素
Set,不可以有重复元素
Map 键值对的形式存在,一对一映射
- ArrayList底层用的Object数组,而linkedList用的双向列表。
- 两者都是不同步的,也就是说不保证线程安全
- linkedList指定插入,添加删除就是O(n),指定位置i插入和删除元素都是O(n)
- arraylist的话,插入会默认在末尾插入,就是O(1),指定插入删除就是O(n)
- Arraylist支持随机访问linkedList不支持
- ArrayList浪费的空间在于,在最后会有一部分空间,而linkedList每一个元素的存储会比较小号空间
Vector是线程安全的,但是比较慢
ArrayList的扩容机制 HashMap和Hashtable的区别- HashMap 非线程安全,HashTable线程安全(其中的方法都经过Synchronized修饰)
- HashMap效率更高(非线程安全的数据结构相对来说都会有更高的效率)
- HashMap底层的数据结构是红黑树
TreeSet底层用的是红黑树,按照元素顺序进行遍历
linkedHashSet是Hashset的子类
HashSet是Set的实现类,HashSet底层是HashMap,线程不安全
Collection下面的集合
-
List
- ArrayList
- Vector
- linkedList
-
Set
- HashSet
- linkedHashSet
- TreeSet
Map
- HashMap
- linkedHashMap
- Hashtable
- TreeMap
进程是程序的一次执行过程
线程与进程相似,是一个比进程更小的执行单位。进程执行的过程中产生很多线程,系统在线程中切换的代价,比在进程级别切换的代价要小。
同一个进程的线程共享进程的堆和方法去,但是每一个线程都有自己的程序计数器,虚拟机栈和本地方法栈。
程序计数器可以发出指令,计数器是这么读取指令的嘛,所以程序计数器一定是需要独立的。
- 线程是比进程更小的执行单位,切换成本较小,减少了线程上下文的开销
- 高并发
- 切换线程,就属于上下文切换
- 互斥条件
- 请求与保持条件
- 不剥夺
- 循环等待
上面是条件
- 两者最主要的区别是Sleep()没有释放锁,而Wait()方法释放了锁
- 两者都可以暂停线程的执行
- wait()用于线程通信,需要等待被唤醒,而sleep()会自动苏醒
前者相当于在main()方法下调用一个方法,不是多线程。
先start()再run相当于让线程准备好了,等待cpu分配时间片,分配到时间片后开始运行。
Synchronized的存在是为了解决多个线程访问资源的同步性。
被Synchronized方法修饰的代码块和方法可以保证在某一个时刻,只有一个线程在调用它
volatile是和Synchronize互补的存在,是轻量级的Sychronized,可以帮助变量可见
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
Runnable不返回结果和抛出异常,而Callable可以
JVM部分 线程私有的和共有的- 程序计数器
- 虚拟机栈
- 本地方法栈
共有的
- 堆
- 方法去
- 直接内存
程序计数器是一个较小的内存空间,当做指令的指示器即可
java虚拟机栈java虚拟机栈也是线程私有的,它的生命周期和线程相同,描述的是java方法执行的内存模型
本地方法栈 Java对象的创建过程- 类加载检查,查询这个类是否被加载过,如果没有加载需要加载到内存中
- 为新生对象分配内存
- 内存分配完成后,虚拟机将分配到的内存空间初始化为0值
- 设置对象头,放一些对象的基本信息在其中
- 执行init方法
Java堆是垃圾收集器的主要区域,被称为GC堆,从垃圾回收的角度,Java的堆可以分为新生代老生带,相当于对象在新生代创建,经过几次垃圾回收,增加它的年龄,到老生代,再过几次垃圾回收机制就被销毁。一些大对象直接进入老年代
废弃常量和无用类没有引用指向这个对象说明是一个废弃常量
判断无用类
- 所有实例都被回收
- 加载该类的ClassLoader已经被回收
- java.lang.Class没有被引用
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)