java代码跨平台原理:
java跨平台性是通过虚拟机jvm来决定的,jvm就是软件模拟的计算机
jvm:相当于是操作系统+硬件环境
那具体什么是jvm,它放在什么地方?
jdk->jre->bin and lib,我们可以把bin酒当成jvm,lib就是jvm工作需要用到的基础核心库类
说一下jre:java runtiime envirtime Java运行时的环境和一些基础库类
jdk包含了jre, jdk的安装:注意安装路径,和改变一下jre,改成功能不可用
什么是JDK:
jdk全英文是:java development kit java开发工具包,也就是必须用它来编译.java代码文件
这个说白了也就是javaee开发对应的jdk版本,有时候我们会听到java7,java8,java10,那么这些都是对应的jdk的版本比如市面上现在比较流行的java8,那么对应的就是jdk1.8,javase8,具体关系可以看如下图:
从上面这张图很明显可以看到,jdk的命名已经变成了java se 版本号来命名了
JDK里面包含了java运行环境,java开发工具,java基础库类
下载位置:
Oracle | Cloud Applications and Cloud Platform
配置环境变量:
%变量名(一般是一个地址路径,不带最后一个地址,单独设置,下划线大写命名)%\地址;
或者直接在path后面加上完整路径和一个分号结束(一般我们应把这个地址放到最前面,否则如果安装了旧JDK,就会出现路径查找错误)
path:path是Windows系统用来指定可执行文件的完整路径。如果执行的可执行文件不在当前目录下,那就会依次搜索path中设置的路径。
- classpath:这个是寻找类文件,rar,zip文件的路径。如何设置当前目录(.)
set classpath=.;设置路径 与 set classpath=设置路径;.有什么区别?
“.”在前面的时候,java虚拟机会先从当前路径去寻找class文件,然后再到指定的路径去需找。如果”.”在后面,java虚拟机则会先寻找指定好的路径,然后再在当前的路径去寻找。
设置classpath的时候要加上 ; 就会在当前目录下查找
E:\>java -classpath D:\java\javase\code Hello
hello world
我们不想这样每次设置一下-classpath 我们想全局来使用
下面看一下CLASSPATH:
注意最后结尾处除了有多个classpath,不然是不加分号的
下面来说一下如何在电脑上安装两个不同的jdk版本:
我的电脑上安装的是jdk7与jdk8的版本
先来看JAVA_HOME的配置,这里直接改JAVA_HOME就行
然后还是直接在path里面引入JAVA_HOME就行了
简单说一下Java的代码编写规则(建议):
1.成员变量、方法、参数、局部变量全部采用小驼峰方法编写
2.java文件名首字母大写,与类名一样
3.常量名全部大写,单词用下划线隔开
4.抽象类用Abstract开头,异常类名用Exception结尾,测试类前面是测试类名,按照Test结尾
5.包名采用小写
6.杜绝不完整,不规范的缩写
7.采用英文单词命名
8.缩进采用4个空格
9.接口类中的方法与属性不加任何修饰符
上面只是大致说了一些规范,具体规范可以参考阿里巴巴java开发手册
至于变量的定义使用与c语言一样,显示隐式转换与c语言一样,乘除法与c一样。
java的数据类型:
这里插入一下java的数据类型:
这里引用数据类型还有一个就是String,也就是我们所熟知的字符串类型
这里说一下,JAVA设置布尔类型变量的时候,必须把布尔类型全部写完,比如
boolean flag=true;在有一些语言中,比如php,他可能就死bool来定义,这是一个细微的差别需要注意
再来对比一下C语言的数据类型:
·简单说一下,基本数据类型基本一致,只不过在java里面整型中多了一个byte数据类型,这个占了一个字节,另外一点就是凡是面向对象编程的语言,都有两个非常显著的数据类型就是字符串与布尔类型。还要说一点就是在C语言中char是占一个字节的,但是在java里面char占用两个字节。
说几个点:
1.在java中,整型默认是int类型的,浮点数默认是double类型的,但是你在写java的时候,会发现一个问题就是,比如byte a = 3;好像可以直接来定义,但是3是int ,这不就是int->byte的一个自动转换嘛,对,确实是自动转换,从大的数据类型变成小的数据类型,这里java是默认可以的,但是必须保证在精度范围之内,否则会造成数据丢失。一般来说int都可以自动转换成byte short char,有人说为什么int -> char,因为char本身的ascii码就是一个整型数据,每一个字符都会对应一个ascii码,对于英文单词来说是这样,所以他们也可以这样正常加减是没有问题的。在C语言中,除了小的转大的,不用显示指定数据类型,其余都要,因为这里会考虑到数据精度缺失问题。在java中对于整型还有一个问题,说了,byte、short、char可以从Int隐式转换,但是不能隐式转换成long,比如long num = 123;是不可以的,只能这样long num = (long)123 或者long num = 123L,这个和C语言声明long有点像。
2.在java中如果float f = 1.23,这样是不可以的,因为默认1.23是doule数据类型的,所以我们必须这样来定义float f = 1.23f 来表明是float的浮点型,或者float f = (float)1.23这样来数据类型显示转换一把。
3.在java中每一种基本的数据类型都有它的对象类型,这个也就是自动装箱与拆箱的问题,java你想想毕竟是一个对象,比如Int-》Integer,这个Integer就会有很多方法在里面可以调用,当我们涉及到数据的运算的时候,Integer定义的数据就会自动拆箱成基本数据类型来计算,然后如何要把数据放到集合里面,又要自动装箱,变成相应的对象,因为集合不能存放基本数据类型。常见的数据类型与它的包装类型展示一下:
常见的运算符与运算符的优先级:
优先级就是与变量接触才会产生优先级
关于判断的运算符:
在使用比价运算符的时候,要求数据类型必须一致。
~:按位取反,就是1变成0,0变成1(这个和!逻辑非优先级都是比较高的)
&&:这个是短路与,短路与,就是左边只要为假,就不进行右边的判断了。
算术运算符:
这里说一下++,--的问题,就说一个就行
比如n++->先使用n在++,比如--n,先把n减了之后在使用。
这里再来说一下原码,反码,补码:
上面就是数据表现的三种形式,数据最终在内存中是都是按照补码进行存放的,这里包括汉字也是一样。
那么这里就先来说一下,首先,内存是按照二进制来保存数据,二进制又分为正数和负数,那么怎么区分二进制的正负,高位是1表示负数,高位是0表示正数,什么是高位,简单来说,左边是高位,右边是低位,最右边的一个数就是表示正负。
举个例子,比如byte num = -2,那么这个数据在内存中就占了一个字节,并且是负数那么它的原码就是10000010,一个字节八个位,最左边的就是高位。
所以,原码是数据最直观的展示形式。那么什么是反码?反码,就是在原码的基础上,保持符号位不变,然后数据0变1,1变0这样一种形式。那么上面-2的反码就是11111101
那么现在就要说,计算机内存实际存放的就是补码,补码就是在原码的基础之上+1,那么-2的反码+1,就变成了11111110
正数原码,反码,补码都是一样。
函数重载的问题:
函数重载:这个与C++语言类似
根据参数类型不同,参数的个数不同,与返回值是没有关系
数组:
同一种数据类型的集合
c/c++: int arr[数组长度]={初始化}; int arr[2][3]={....}|{{},{}}
php:array(数据集) $arr=Array(“键”=》”值”),他可以不用数据类型完全一致
javascript:var arr1=new Array() 里面可以传值或者一个数,那么这个数就代表长度
var arr2=[] //这个里面放上数据/数据可以是任何类型的
OK,那我们来看一下java
它与c/c++是相反的,[]是放在数据类型的前面。
int[] arr=new int[3]//说明有三个数据,可以在后面来给这三个数据
int[] arr=new int[3]{1,2,3};
int[] arr={直接给数据};
java获取数组长度,数组名.length
二维数组:
可以javascript类比java,,它也可以直接调动这个类,然后来进行操作,原因在于它把所有函数全部设置成了一个静态函数。
比如Arrays.函数,Math.函数
类比:
int[][] ar=new int[一维数组个数][每一个一维数组个数
来看一道关于数组的面试题:
面试题:把一个数组里面的0全部清空,然后返回一个干净的数组
比如这个数组:int[] arr = {0,0,12,1,4,0,18};
我们需要返回这个:int[] arr = {12, 1, 4, 18}
下面直接上核心代码:
//计算新数组需要的长度
int newLen = 0;
int oldLen = oldArr.length;
for(int i = 0;i < oldLen;i++) {
if((int)oldArr[i] != 0) {
newLen++;
}
}
System.out.println("数组的长度的是:" + newLen);
//然后来建立一个新数组
Object[] newArr = new Object[newLen];
//在来给新数组赋值
int index = 0;
for(int j = 0;j < oldLen;j++) {
if((int)oldArr[j] != 0) {
newArr[index++] = oldArr[j];
}
}
return newArr;
数组小问题:
在声明的数组的时候,一定要确定好长度,不管是直接给数据,还是定义长度都要明确数组长度
这里说一下二维数组:
int[] arr=new int[2][];//比如这样来定义数组,确定数组的函数,按照道理来说,每一行,我们确定多少数据都是ok的,比如第一行我放三个数据,第二行我放两个数据,但是我们最好要让数据长度一致,也就是,每一行的数据保持一致,这样才能更好的循环数组里面的数据
下面进入到面向对象的环节:
对象也是可以进行传递的,然后可以调用里面的属性与方法
一个文件里面可以有多个对象,一个文件也可以有多个类,从主类开始一层层划分
这里需要我们注意的是,Java只有一个类或者接口是public的
匿名对象:没有引用类型变量指向的对象称作为匿名对象。
备注:还是可以调属性的,但是它的属性也是一次性的
匿名对象要注意的事项:
1. 我们一般不会给匿名对象赋予属性值,因为永远无法获取到,即时即用
2. 两个匿名对象永远都不可能是同一个对象。
匿名对象好处:简化书写。
匿名对象的应用场景:
1. 如果一个对象需要调用一个方法一次的时候,而调用完这个方法之后,该对象就不再使用了,这时候可以使用匿名对象。
2. 可以作为实参调用一个函数。
需求: 使用 java类描述一个学生类。
//学生类Student
class Student{
int num; //学号
String name; //名字
public void study(){
System.out.println("好好学习,为将来称为高帅富做准备!");
}
}
一个测试类Demo4
class Demo4{
public static void main(String[] args) {
//创建一个学生对象
//Student s = new Student();
//new Student().name = "狗娃"; //匿名对象
//System.out.println(Student().name); //null这个对象与上一个不是同一个对象
System.out.println(new Student() == new Student()) ; // "==" 用于引用类型变量时,比较的是内存地址。判断两个 对象是否为同一个对象一般来说是引用的这个地址
需求: 调用Student的study方法。
Student s = new Student();
s.study();
new Student().study()
}
}
下面来看一个没有封装的类,这是一个表示职工的类Employee
然后写一个主方法来创建这个类的对象,并且赋值各种操作
说的简单一点就是是个人就可以去修改,那我们如何实现封装,把里面的成员属性,全部设置成privaet,只保留有限的对外接口就可以了。然后,就不能直接通过类的对象名.属性直接访问,不然肯定会报错。
封装的思想就是要保护数据。
比如我们给一个public set方法和get方法
对于每一个属性我们都可以提供这样两个方法,一个设置,一个获取。
解释一下x.equas(y):当x与y是属于同一种对象时,并且值相等时,就返回true,否则返回false
后面会特别具体的来说明一下这个问题
封装的几个好处:
1.隐藏了类的具体实现
2.操作简单
3.提高对象数据的安全性
下面来说构造方法:
构造方法,是你在实例化一个对象,然后往对象属性里面赋值的一个方法。定义与类名相同的方法即可被自动调用。可以添加常见几种权限修饰符进行修饰。
1.构造函数的函数名要与类名一样,而普通的函数只要符合标识符的命名规则即可。
2.构造函数没有返回值类型
需要注意的两个问题:
这里来说一点与c++不同,JAVA如果不用构造函数,可以在定义的时候初始化,当然php也可以在定义的时候进行初始化。c++只能用构造函数进行初始化。注意在java里面,千万不要在主类里面在写类。在java文件中,一般只有一个public类声明
还可以向上面这样来写构造函数
我这里来说一下用this与不用This的区别,加this只是代表这个对象。调用这个函数的对象是谁,因为New一个对象空间都是独立的,那么这个对象也是独立的。
如果不用这个this,javac编译也不会报错,因为他本身就是有默认值的