1、java编译和运行阶段发生的事情,如下图所示:
- 编写的java源文件,通过java编译器编译生成以.class结尾的字节码文件(字节码并不是二进制),生成的字节码文件通过类装载器装载进java虚拟机中,再通过java虚拟机运行转化成二进制文件与底层的操作系统交互,实现在硬件平台上运行。(java的可移植性)
2、在安装数据库(如oracle和mysql)或者jdk软件开发工具包等软件时,安装路径上尽量避免不要有空格或者是中文。
3、windows操作系统中在命令行窗口中执行命令ipconfig,可以显示本机的ip地址,原因是在系统变量path路径上配置%SystemRoot%\system32;(%SystemRoot%在我的电脑中是指C:\Windows):
- 如果没有在环境变量中找到配置ipconfig命令对应的目录,则会显示以下内容:
- 要想刚配置的环境变量中的命令在命令行中生效,需要退出当前的命令行窗口后重新打开。
- 需要注意Administrator的用户变量只对Administrator用户系统起作用,而系统变量对所有的用户系统起作用,所以一般配置环境变量都是在用户变量中配置PATH。
4、javac命令后面跟的是路径,绝对路径或者相对路径。
- java命令后面跟的是类名,java命令键入后会启动java虚拟机,java虚拟机默认在硬盘当前路径下查找对应类的.class文件,并将其装载到虚拟机中。(可以在环境变量中配置CLASSPATH变量,配置后java虚拟机会在CLASSPATH指定的目录下搜索.class文件,而不会在当前路径下查找)
5、java类体中不能够直接编写java语句。
- 一个.java源文件中可以定义多个class,并且一个class类名生成一个.class文件。
- pulic的class的名字必须与文件名保持一致。(一个java源文件中只能有一个public的类名,源文件中也可以没有pulib类)
6、标识符通俗的理解为在java源文件中凡是自己可以起名字的地方都是标识符,如类名、变量名、方法名、接口名。
- 标识符语法规则命名必须由字母、数字、下划线或者美元符组合而成,并且不能够以数字开始,关键字不能够作为标识符,并且标识符严格区分大小写,最好见名知意。(理论上长度不限制)
- java规范中类名的第一个字母大写,后面每个单词字母大写。(遵循驼峰式命名规范)
7、关键字都是小写命名,关键字就是sun公司定义开发java语言的使用的字符序列。
- java语言中的字面值,一眼看上去就知道多少的数据,字面值有数据类型,包括整型、浮点型、布尔型、字符型、字符串型,在内存中占用空间。(字面值就是内存中的一块空间,这块空间有类型、有值,而只用字面值内存无法得到重复利用)
- 字符字面值只能用单引号括起来,字符串字面值只能用双引号括起来。("A"是一个字符串)
- int a; 含义是在内存中开辟一块空间,这块空间的类型是整型,给这块空间起名为a。(单独字面值在内存中只有值,无法给重复利用,而变量在内存中有名字,有类型,也有值,可重复利用)
- 变量可以重新赋值,但是不可以重复声明。(在同一个域中,如short a = 10; char a = ‘a‘;不能通过编译)
- java语言中的变量必须先声明,再赋值,才能够使用。
- int i1,i2,i3 = 456;声明了三个变量i1,i2,i3,类型是int整型,其中i1,i2,i3是整型,i1,i2未初始化,i3初始化为456。
- 关于变量的作用域:有效范围或者作用范围,即出大括号就不认识。(在for循环中声明的局部变量,出了大括号后就无效)
- 根据变量出现的位置可以分为两种:局部变量(在方法体中声明的变量叫做局部变量,包括形式参数列表)和成员变量(在类体中,方法之外声明的变量统称为成员变量)
8、八种数据类型的取值范围:
- 一个字节等于八位,八位是指八个二进制位,十进制数-1在java语言中使用二进制表示10000001,1表示为00000001。(在java语言中首位为符号位,所以八位二进制最大表示为01111111,即为十进制的127)
- 在java中boolean值只能够用true和false表示,没有其他值,不能够为0和1。
- 十进制转换成二进制:除二取余,逆序输出。
- 从字符到计算机的二进制位称之为解码,从计算机的二进制位到字符称之为编码。例如,‘a‘对应十进制数97,‘A‘表示十进制数65,‘0‘表示十进制48。
- 字符编码方式是现实世界中的文字和计算机的表示方式的转换规则。
- java语言中的char字符类型采用unicode字符编码方式,使用utf-16实现,,底层占用两个字节。
- 字符如果采用的编码和解码不一致的话,会出现乱码问题。(汉字占用两个字节,所以java中的char可以表示汉字)
- “\”斜线在java语言中有转义功能。可以将普通t字符,转换成“制表符”;可以将普通n字符,转换成“换行符”;
- char c = ‘\‘‘;表示一个普通的“单引号”字符,char c = ‘\\‘表示一个普通的“斜线”,使用“斜线”来表示java中有特殊含义的字符。char类型表示的默认值为‘\u0000‘,表示一个unicode编码。
- Java语言中有三种方式表示整型值:0x表示以十六进制值,0表示以八进制值以及十进制。
- Java语言中整型值默认为int类型,int i4 = 100;将一个int类型的100字面值赋值给i4变量。long l1= 123;将一个int类型的123字面值赋值给long类型的l1,int类型容量小于long类型,程序会进行自动类型转换。(123L字面值是long类型数据,L为大写)
- long l1= 100L; int i1 = l1;将long类型转换成int类型,不能够自动类型转换,需要强制类型转换。(大容量向小容量转换,需要强制类型转换,程序在运行阶段可能损失精度,所以一定要谨慎使用)
- byte b = 127;编译通过,byte b = 128;编译不能通过。即如果这个整数没有超出byte的取值范围,可以直接将这个整数赋值给byte类型。
- short s = 32767;编译通过,short s = 32768;编译不能通过。即如果整数本身没有超出short的取值范围,可以将这个整数直接赋值给short。(也包括char,char c = 65535;编译通过,char c = 65536;编译不能通过)
- 浮点型字面值默认是double类型,float f = 3.2;编译不能够通过,可以通过强制类型转换或者在数值后加F。(浮点型加F表示float类型)
- boolean类型的数据主要用在逻辑运算和条件控制语句中。(boolean b = 1;编译不能通过,赋值只能是false或者true)
- 在java中基本类型可以相互转换,boolean类型比较特殊不可以转换成其他类型。
- 默认转换:容量小的类型会默认转换成容量大的类型,即:byte --> short(char) --> int --> long --> float --> double。byte、short、char之间做混合运算的时候,各自转换成int后再做运算。(编译阶段只会检查语法,运算阶段才会进行计算。byte b1 = 10; short s = 20; byte b2 = b1 + s1;编译不能通过,原因是编译阶段检查语法,b1 + s1使得byte类型的b1和short类型的s1都转换成int,结果为int类型【此时没有计算出相加后字面值】而int类型不能够自动转换成byte类型,运行阶段才会计算出b1 + s1的字面值30)
- 在多种类型混合运算过程中,首先先将所有数据转换成容量最大的那种,再运算。
- int f = 10/3;可以通过编译,因为字面值整数10和3都是int类型,相除后的结果为int类型。
- long g = 10;int h = g/3;不能通过编译,因为在编译阶段检查语法,编辑阶段只知道g/3结果为long类型,而long类型转换成int类型需要强制类型转换(并不会计算出g/3的字面值3,计算值是在运行阶段所做的事情)
9、int m = 10;int e = m++;变量m值为11,变量e为10。(需要考虑=和++的优先级,如果++在变量后,=运算符优先级更高些)
- int z = 10;System.out.println(z++);输出结果为10,z++可以理解为z = z++,先赋值后自增1。
- 关系运算符的运算结果一定是boolean类型。(不知道运算符的优先级就加括号)
- 布尔运算符(&逻辑与、|逻辑或、!逻辑非、^逻辑异或、&&短路与、||短路或)两边的算子必须是布尔类型,整个表达式的运算结果也是一个布尔类型。
- true^false -> true,false^true -> true,true^true -> false,false^false -> true
- int a = 10;int b = 10;System.out.println(a < b & a++ >=b);System.out.println(a);运行后a为11,说明逻辑与、逻辑或不会发生短路现象。
- &&短路与、||短路或的短路现象是后一个表达式可能不执行。(当&&短路与前一个表达式为false时,后面的表达式不执行,因为结果已经能够判断)
- 基本赋值运算符(=)和扩展赋值运算符(*=、+=、-=、/=、%=)的区别:byte i = 10;i = i + 10;编译无法通过,编译期运算结果是int类型(运行期时才计算结果值,编译器只判断类型),前边的变量是byte类型。i += 10;编译可以通过,扩展运算符不改变运算结果类型,可能会损失精度。i += 1000;编译可以通过,但是严重损失精度。
10、if语句只要一个分支执行,则整个if语句结束。
- String不是基本类型数据,是引用类型。
- switch语句中的break和default语句可以没有。(如果没有break语句,则发生case穿透现象)
- switch后面的括号中可以填写byte/short/char类型,因为可以自动转换成int类型。(switch语句括号如果放置数值,只能放置int类型数据)
- for循环语句:for(表达式1;表达式2;表达式3){java语句}表达式1是初始化表达式,最先执行,只执行一次;表达式2是boolean类型的条件判断表达式;表达式3为操作语句。
- while循环语句的循环体中循环次数可能为0次,do...while...循环至少执行1次。
- break语句:可以用在switch语句中,结束分支语句;也可以出现在循环语句中,默认情况下结束离他最近的一个循环。(return语句结束方法,是方法级别的,break语句是循环级别,结束循环)
- continue语句可以用来结束当前最近循环中的本次循环,直接进入下一次循环继续执行。
- 可以通过标签名使得break指定结束某个循环,而不是结束最近循环。(continue语句同理)
11、加有static的方法,调用的时候必须采用“类名.”的方式调用。(方法就是一段代码片段,这个片段可以完成特定的功能,并可以重复利用)
- 定义方法的语法:[方法的修饰符列表] 方法的返回值类型 方法名(方法的形式参数列表){java语句;},其中方法的修饰符列表是可选项;方法的返回值类型,可以是java语言中的任意一种数据类型(基本数据类型或者引用数据类型);如果该方法执行结束之后,并没有任何返回值,那么定义方法的时候,返回值类型为void;方法的形式参数列表,可以有参数,也可以没有参数,如果有多个参数的话,使用“逗号”隔开。(形式参数为局部变量,参数的名字是随意的,只要是合法的标识符即可)
- 如果一个方法的返回值类型不是void,那么方法体中的必须使用return语句返回数据,return语句一旦执行,则方法结束。(返回值的类型和return语句的类型需对应。如果返回值类型为void,则return;语句可选)
- 方法调用时传递的参数被成为实参,实参列表中的实参的类型和个数需与形式参数列表的形参相对应。
- static方法如果在当前类中,调用这个static方法可以省略类名。
- 使用return;来结束方法返回值类型为void方法,以此来结束方法。(return;
System.out.printlin("abc");不能通过编译,错误显示为无法显示的语句)
- 方法的重载(方法名相同,参数列表不同【个数不同、顺序不同、类型不同都可以】,方法重载与返回值类型、修饰列表无关)的优点:方便程序员记忆,代码美观。(方法重载发生在同一个类中),System.out是PrintStream类型,println方法构成了方法的重载。
- 栈(stack)存储数据的特点:后进先出。将元素(元素也叫做栈帧)放入栈中叫做压栈或者入栈(push),将元素从栈中取出叫做出栈或者弹栈(pop)。第一个元素叫做栈顶元素,最后一个元素叫做栈底元素。
- 方法的执行原理:方法在调用的时候,才会给该方法在内存中分配空间。如果这个方法只是定义没有调用,则不会在内存中分配空间。(方法在调用的时候,在“栈”中分配空间,JVM内存中有一块内存是栈内存,所以方法调用其实就是“压栈”,方法调用结束其实就是“弹栈”。栈空代表程序结束。)
- 方法的递归调用:方法自身调用自身。(可能会出现java.lang.StackOverflowError,能不用递归就不用,递归效率并不高。)
12、面向过程和面向对象的区别:采用面向过程必须了解整个过程,每个步骤都有因果关系,每个因果关系都构成了一个步骤,多个步骤就构成了一个系统,因为存在因果关系每个步骤很难以分离,当任何一步出现问题,将会影响到所有的系统。(面向过程的应用程序代码之间的耦合度非常强);面向对象将现实世界分割成不同的单元(对象),实现各个对象,如果要完成某个特定功能,只需要各个对象组合即可。
- 面向对象的三大特性:封装、继承、多态。类是对具有共性事物的抽象描述,是在概念上的一个定义。(类是引用数据类型,可以认为是一个模版)对象是具体存在的个体,也叫做实例,就是一个类的具体化或者实例化。
- 面向对象更符合人的思维模式,更容易的分析现实世界,从软件开发的生命周期来看,基于面向对象可以分为三个阶段:OOA(面向对象的分析)、OOD(面向对象的设计)、OOP(面向对象的编程,Java就是一个纯面向对象的语言)
- UML是指统一建模语言, 是一种图形语言。(类 = 属性 + 方法,属性属于对象的状态,方法属于对象的动作。需要注意,成员变量(又称为实例变量)是对象级别的,必须由对象才能够访问,必须使用“引用.”的方式进行访问成员变量,不能使用类直接访问。成员变量如果没有手动赋值,系统会默认赋值。(静态变量使用类名来直接访问))
- java中所有new出来的数据统一存储在堆(heap)中,程序员无法对堆中的数据直接操作,只能通过对堆中的内存地址间接操作。(堆中的对象的内存地址可以赋值给局部变量,这个局部变量也称为引用,通过局部变量进行操作)
- 局部变量是在方法中定义的变量,方法的参数,方法的返回值,局部变量使用前必须初始化,而成员变量会默认初始化,初始化的值为该类型的默认值。系统默认值:byte、short、int、long -> 0,float,double -> 0.0,boolean ->false,char -> \u0000,引用数据类型 -> null。
- 一个类可以创建N个对象,成员变量只属于当前的对象(只属于对象,不属于类),只有通过对象才能够访问成员变量,通过类不能直接访问成员变量。
13、面向对象的封装性值得是属性私有化和对外提供公开的setter and getter方法:对成员变量添加private修饰,表明只能在本类中访问。可以对外提供两个公开的方法供外部设置和读取实例域。(setter、getter方法可以进行安全控制,此类方法是成员方法或者说是实例方法,而非静态方法,成员方法必须使用“引用.”的方式访问)
- 构造方法语法:[修饰符列表] 构造方法名(){方法体;},构造方法的方法名必须和类名一致。构造函数使用 (new 构造方法名(实参))语法来创建对象,在堆中开辟空间存储对象。(也可以初始化成员变量,也可以说是给成员变量赋值)
- 如果一个类没有提供任何构造方法,系统默认提供无参数的构造方法;如果一个类已经手动的提供了构造方法,那么系统不会再提供任何构造方法。
在类通过类装载器加载进java虚拟机时,不会给成员变量赋值。只有在调用构造方法的时候,才会给成员变量赋值。(可以认为在构造函数中首先给对象中成员变量赋默认值)
- Java虚拟机管理的内存有三个区:堆区、栈区和方法区。堆区:存放new出来的对象,此对象由垃圾回收机制收集,垃圾收集器,针对的就是堆区。栈区:每调用一个方法,会创建一个栈帧,存放局部变量。方法区:类的所有信息,包括所有的方法,静态变量和常量。
- User u = new User();(u是引用,保存内存地址指向堆中的对象)u = null;(程序执行到这,u不再指向堆中的对象,对象变成了垃圾。)System.out.println(u.name);(编译可以通过,语法上没有错误,使用一个空的引用去访问成员(成员变量或者成员方法),会发生空指针异常,即java.lang.NullPointerException。)
- 程序在执行过程中,参数的传递问题:以下程序传递的数据是基本数据类型:(局部变量只有在方法中有效)
- 程序在执行过程中,参数的传递问题:以下程序传递的数据是引用数据类型:(方法中传递的参数是引用,即传递的是内存地址,指向的是同一个对象)
- java中只用值传递,没有引用传递。
- this关键字:this是一个引用类型,在堆中的每一个java对象上都有this,this保存内存地址指向自身。
- this能用在那些地方?this可以用在成员方法中。this可以用在构造方法中。(this用在成员方法中,谁调用了这个成员方法,this就代表谁。this.可以省略,可以表示对象中的成员变量或者成员方法,可以用于区分成员变量和局部变量)
- this不能用在静态方法中:静态方法的执行根本不需要java对象的存在,直接使用(类名.)的方法访问。而this代表的是当前对象,所以静态方法中根本没有this。(编译期就会报错,报错内容为:静态方法上下文中不能够引用非静态变量this)
- this可以用在构造方法中,通过一个构造方法调用另一个构造方法,目的在于代码重用。语法:this(实参)。(只能出现在构造方法的第一行中)