-
JRE与JDK
JRE(Java Runtime Environment Java运行环境):
包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
JDK(Java Development Kit Java开发工具包):
JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包括了JRE,所以安装了JDK,就不用在单独安装JRE7。
其中的开发工具:编译工具(javac.exe)打包工具(jar.exe)等
简单而言:使用JDK开发完成的java程序,交给JRE去运行。
-
原码、补码、反码
数字以原码的形式存在、计算时以补码进行计算
-
变量相加、常量相加
Java有常量优化机制,编译时直接将常量相加的结果当成一个数。
A:在定义Long或者Float类型变量的时候,要加L或者f.
- 整数默认是int类型,浮点数默认是double.
- byte,short在定义的时候,他们接收的其实是一个int型的值.
- 这个是自己做了一个数据检测的,如果不再它们的范围内,就报错.
B:byte值的问题
- byte b1=127;byte b2=(byte)300;byte b4=(byte)130;
- byte的范围:-128 ~ 127
C:数据类型转换之默认转换
- byte,short,char--int--long--float--double long:8个字节float:4个字节
- IEEE754
- 4个字节是32个二进制位
- 1位是符号位8位是指数位
- 23位是尾数位
- 每个指数位减去121
- A:它们底层的存储结构不同。
- B:float表示的数据范围比long的范围要大
- long:2 63-1
- float:3.4*10-38 > 2*10~38 > 2"8-38-2*2^3~38-2*2 114 > 2~63-1
D:Java语言中的字符char可以存储一个中文汉字吗?为什么呢?
- 可以,因为Java语言采用的是Unicode编码.Unicode编码中的每个字符占用两个字节.
- 所以,Java中的字符可以存储一个中文汉字
-
键盘输入输出
import java.util.scanner;
scanner sc = new scanner(System.in);
int x = sc.nextInt();//输入
System.out.println("输出:"+x);
-
运算符
^:相同为0,不同为1,一个数据对另一个数据位异或两次,该数本身不变。
<<:左移 左边最高位丢弃,右边补齐
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移无论最高位是0还是1,左边补齐0
-
转移字符
- '\t':tab键的位置,制表符
- '\r':回车
- '\n':换行
-
Java内存分配
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
- 栈存储局部变量(在方法中和方法上定义)
- 堆存储new出来的东西
- 方法区(面向对象部分讲)
- 本地方法区(和系统相关)
- 寄存器(给CPU使用)
栈也叫内存,是Java程序的运行区,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就over。
栈中的数据都是以栈帧(stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关 方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法又调用了B方法,于是产生栈2也被压入,执行完毕后,先弹出F2栈帧,再弹出F1栈帧,遵循"先进后出"原则。
那帧中到底存在着什么数据呢?栈帧中主要保存3种数据:
- 本地变量(Local Variables),包括输入参数和输出参类似及方法内的变量;
- 栈操作(operand stack),记录出栈、入栈的操作;
- 栈帧数据(Frame Data),包括类文件、方法等等。
-
垃圾回收机制
栈中变量使用完毕就出栈,线程结束该栈也就释放。
堆中对象:当没有任何引用指向堆内存的对象的时候,该对象变成垃圾。jvm的垃圾回收机制,会在不定时对其进行回收。
-
Java中到底是传值还是传址?
1,Java中即传值也传址,基本数据类型传的是值,引用数据类型传的是址(地址)
2,Java中是传值,非传址,因为地址值也是值(高司令支持)
change()中对传入的arr数组进行操作,因为传入的数据是引用数据类型(指针、数组),是堆中的地址,所以操作以后数据改变了。
如果传入的是基本数据类型(int等),这时change()中操作的值是栈中保存在change方法内的变量,运行完以后栈中change()释放,所以保存在栈的main()中数据没有改变。
-
对象的内存
方法用完就出栈。new出来的东西(实例)存在堆中。方法区存的是每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
-
匿名对象易产生垃圾
-
static
在类中变量定义为static后,这个变量就变成对象之间共有的了,保存在方法区中,其他的非静态成员变量保存在堆中各自的对象中。
非静态的成员方法可以访问静态的成员,静态方法不能访问非静态的成员。(因为静态成员是优先于对象存在的,是随着类加载而加载的,所以他不能知道后续创建的对象中有什么)
静态的成员方法也没有this关键字,因为this是随着对象的创建而存在的。
所以成员方法中加了static以后,可以“xx类.xx方法”直接调用,如果没有加static,就必须先创建(new)一个该类对象x,然后"对象x.xx方法"调用。
静态变量可以通过类名调用,也可以通过对象调用;成员变量只能通过对象名调用
-
public static void main(String[]args)()
public被jvm调用,访问权限足够大
static被jvm调用,不用创建对象,直接类名访问
void被jvm调用,不需要给jvm返回值
main一个通用的名称,虽然不是关键字,但是被jvm识别
string[]args以前用于接收键盘录入的
-
Java中类的继承的特点
Java不支持多继承,但是支持多层继承
子类只能继承父类的非私有成员,子类不能继承父类的构造函数,但是能通过super语句访问父类构造方法。
什么时候使用继承?如果有两个类A,B.只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
不要为了部分功能去使用继承。
继承中父类子类中同名成员变量的关系:就近原则,自己有就不用父类的,super可以调用父类的成员变量。
-
方法重写override、重载overload
父类中私有方法不能被重写,因为父类私有方法子类根本就无法继承。
子类重写父类方法时,访问权限不能更低,最好就一致
父类静态方法,子类也必须通过静态方法进行重写,其实这个算不上方法重写,但是现象确实如此。
overload可以改变返回类型,overload方法名相同,参数列表不同。
override方法名参数列表与父类方法的都相同。
子类调用重写方法:创建子类对象,先从子类找方法,如果没有就找父类的。
-
final
final修饰类,类不能被继承。
final修饰方法,不能被重写。
final修饰变量,被称为常量,不能被修改。
final修饰引用数据类型,地址不能改变,但是地址指向的值可以改变。
final修饰成员变量必须要初始化,可以在定义时直接赋值,也可以在构造函数中赋值。
-
多态
三个前提:
继承、重写、父类引用指向子类对象。
Animal父类,Cat子类,调用非静态的重写方法时,编译时看的是父类的方法,执行时看的是子类的方法(动态绑定)。
因为静态方法是属于类的,所以静态方法不存在覆盖一说。调用静态的重写方法时,编译时看的是父类的方法,运行时也是父类的方法。
成员方法:编译看父类,执行看父类。
向上转型:父类引用指向子类对象(自动类型提升)
多态的好处:提高了代码的维护性(继承保证),提高了代码的扩展性(由多态保证)
弊端:不能使用子类特有功能。
-
抽象类
抽象类和抽象方法必须用abstract关键字修饰:
abstract class 类名{ }
public abstract void eat();
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
抽象类不能实例化(创建对象)那么,抽象类如何实例化呢?通过继承抽象类。按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
抽象类的子类:要么是抽象类、要么重写抽象类中的所有抽象方法