步骤:编写源代码,编译源代码,装载,校验,运行
①平台无关性(一次编写,随处运行 )
②面向对象(封装,继承,多态)
③健壮性(鲁棒性,强类型机制,异常处理机制,抛弃指针)
④分布式
⑤多线程(多线程编程,允许程序中多个任务并发执行,提供同步机制允许共享数据)
⑥动态性(允许程序动态地装人运行过程中所需要的类;也可以通过网络来载入所需要的类,能进行运行时的类型检查)
public class HelloWorld{
public static void main(String[] args){
System.out.println("HelloWorld");
}
}
class关键字不能变,全部小写
public static void main(String[] args){ 这个方法叫main方法,除了args可以自行命名,其他的都不可以变,是程序运行的入口
类前面常常使用public修饰,成为公共类
.java文件的名字必须与源文件中的class名字完全一致,大小写也需要一致,如果不一致就会出现编译错误在一个
在一个.java文件中可以有多个Java类,最多只能有(也可以没有)public类,尽量不要在一个文件中存在多个类,可读性比较差
①不同的变量有不同的用途
②区分数据之间的区别
③实现数据的合理存放
④方便计算机读取内存时,通过数据类型,进行正确处理
堆heap:(引用类型(引用,成员变量)存储)
运行时数据区
运行时动态分配内存
自动回收垃圾
存取速度较慢
栈stack(基本数据类型存储)
存取速度快
数据可以共享
数据大小和生命周期必须确定,不够灵活
方法区method area:
用来存储类型信息
常量池constant pool
用来存储类型的常量信息
不同的基本数据类型之间可以相互转换
从范围小的类型转换为范围大的类型,可以直接转换,隐式转换
byte b = 1 ;
int i = -2 ;
//表示范围小的可以直接转换为表示范围大的类型
i = b ;
i = c ;
从表示范围大的类型转换为表示范围小的类型,需要强制转换(显式转换)
byte b=1;
int i=-2;
// 表示范围大的不可以直接转换为转换范围小的类型,需要强制转换,称为显式转换
b=(byte)i;
c=(char)i;
数值类型和Boolean类型之间不能转换,强制也不可以
byte b=1;
boolean b2=false;
// "风马牛不相及"的boolean和数值类型,强制也不能转换;
b2=b; (编译错误)
b2=(boolean)b; (编译错误)
“=”可以为任何一种基本数据类型赋值,但是不能超过表示范围,否则会编译错误
byte b1=127;
byte b2=129;//超出byte的表示范围,编译错误
char类型使用“引用单个字符赋值,也可以使用非负整数进行赋值”
char c1='a';
char c2=12;
char c3='ab';//编译错误
char c4=12.8;//编译错误
char c5=-199;//编译错误
小数默认double
//小数默认为double类型;使用f或F后缀可以表示该小数是float型;
float f1=1;
float f2=1.0;//编译错误
float f3=(float)1.0
float f4=1.0f;
//小数默认为double类型;使用d或D后缀可以显式表示该小数是double型;
double d1=1.0;
double d2=1.0d;
Boolean只有true和false两个值
boolean b3=false;
boolean b4=true;
boolean b5=1;//编译错误
int i1=18;
int i2=19;
System.out.println("i1==i2 "+(i1==i2));
System.out.println("i1!=i2 "+(i1!=i2));
System.out.println("i1>i2 "+(i1>i2));
System.out.println("i1
输出结果:
i1==i2 false
i1!=i2 true
i1>i2 false
i1
//声明两个引用类型变量s1、s2,并使用new进行赋值
String s1=new String("Hello");
String s2=new String("Hello");
//使用==及!=比较s1和s2的地址
System.out.println("s1==s2"+s1==s2);
System.out.println("s1!=s2"+s1!=s2);
当只声明一个引用类型变量,没有为其赋值,该变量的值为null
public class Item0301 {
// 此处不考虑static含义,后续学习;只为了能在main方法中访问;
static String s;
public static void main(String[] args) {
System.out.println(s);
}
}
使用enum关键值可以声明一个枚举,枚举编译后也会生成.class文件,也是一种引用类型
public enum Item0302 {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
注解也称为元数据、是和类、接口、枚举,并列的一种引用类型
Java API中定义了系列注解类型,称为内置注解
除了直接使用API中的注解外,还可以自定义注解类型
@Override
public String toString() {
return super.toString();
}
int a=13;
int b=5;
System.out.println("a/b="+(a/b));
System.out.println("a%b="+(a%b));
System.out.println("a++="+(a++));
System.out.println("++b="+(++b));
System.out.println("a="+a);
System.out.println("b="+b);
}
}
输出结果为:
a/b=2
a%b=3
a++=13
++b=6
a=14
b=6
返回值是true或false
针对操作数的二进制位进行计算
&和|称为非短路逻辑运算;&&和||称为短路逻辑运算
如果存在T1&T2,当T1为false时,返回值已经确定为false,但是依然还会运算T2表达式;所以称为非短路;
如果存在T1&&T2,当T1为false时,返回值已经确定为false,就不会运算T2表达式;所以称为短路;
三目运算符
表达式1?表达式2:表达式3
表达式1为true,表达式2被计算
表达式为false。表达式3被计算
//单行注释
/*.......*/ 多行注释
/**.......*/文档注释
命名规则:
以字母,下划线(_),美元符($)开始
后面可以跟字母,下划线,美元符,数字
不可以使用关键字命名
**关键字:
作用域(scope):决定了变量可使用的范围
全局变量:变量可以在整个类中被访问
局部变量:只能在定义其代码段中被访问
使用局部变量比全局变量更安全
常量时特殊的变量,不能修改值的变量,只能在定义时赋值
定义格式为:
if(判断语句){
}
执行语句1;
} else{
执行语句2;
}
执行语句1;
}else if{
执行语句2;
}else{
执行语句3;
}
表达三目运算符相同的作用
int a = 0 ;
int b = 2 ;
int max ;
if(a > b){
max = a ;
}else{
max = b ;
}
System.out.println("最大值是: "+max)
}
switch/case
public static void main(String[] args) {
int x=2;
switch(x){
case 0:
System.out.println("你将退出系统");
case 1:
System.out.println("请输入用户名及密码:");
case 2:
System.out.println("Pls input your name and password");
default:
System.out.println("请按照提示选择1/2/3进行操作");
}
}
输出结果为:
Pls input your name and password
请按照提示选择1/2/3进行操作
可以在case语句中用break语句控制跳出switch语句
int x=2;
switch(x){
case 0:
System.out.println("你将退出系统");
break;
case 1:
System.out.println("请输入用户名及密码:");
break;
case 2:
System.out.println("Pls input your name and password");
break;
default:
System.out.println("请按照提示选择1/2/3进行操作");
}
输出结果为:
Pls input your name and password
switch/case可以使用:byte,int,short,char。String、enume
不能使用:float、double、long、Boolean
for(初始化语句;条件判断语句;控制语句){
循环体语句块;
}
int a ;
for(a = 0 ; a < 5 ; a ++){
System.out.println("a = " +a);
}
输出结果:
a = 0
a = 1
a = 2
a = 3
a = 4
while(判断条件语句){
循环体语句块;
控制语句;
}
int b = 0 ;
while(b < 5){
System.out.println("b = " +b);
b++
}
输出结果:
b = 0
b = 1
b = 2
b = 3
b = 4
do{
循环语句块;
控制语句;
}while(判断条件语句);
int c=0;
do{
System.out.println("c="+c);
c++;
}while(c<5);
输出结果为:
c=0
c=1
c=2
c=3
c=4
循环可以嵌套使用:
for(int i=0;i<3;i++){
for(int j=5;j>0;j--){
System.out.println("i="+i+" j="+j);
}
System.out.println("结束i的第"+i+"次循环");
}
System.out.println("结束所有i循环");
}
输出结果为:
i=0 j=5
i=0 j=4
i=0 j=3
i=0 j=2
i=0 j=1
结束i的第0次循环
i=1 j=5
i=1 j=4
i=1 j=3
i=1 j=2
i=1 j=1
结束i的第1次循环
i=2 j=5
i=2 j=4
i=2 j=3
i=2 j=2
i=2 j=1
结束i的第2次循环
结束所有i循环
continue不再继续循环体后的代码,开始下一次循环
for(int i=0;i<5;i++){
//判断i是偶数
if(i%2==0){
//如果i是偶数,则继续下一次循环
continue;
}
//输出i的值
System.out.println("i="+i);
}
输出结果为:
i = 1
i = 3
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
//当i==j时,继续j循环
if(i==j){
continue;
}
System.out.println("i="+i+" j="+j);
}
System.out.println("结束i循环的第"+i+"次循环");
}
System.out.println("结束i循环");
}
输出结果为:
i=0 j=1
i=0 j=2
i=0 j=3
i=0 j=4
i=0 j=5
结束i循环的第0次循环
i=1 j=0
i=1 j=2
i=1 j=3
i=1 j=4
i=1 j=5
结束i循环的第1次循环
i=2 j=0
i=2 j=1
i=2 j=3
i=2 j=4
i=2 j=5
结束i循环的第2次循环
i=3 j=0
i=3 j=1
i=3 j=2
i=3 j=4
i=3 j=5
结束i循环的第3次循环
i=4 j=0
i=4 j=1
i=4 j=2
i=4 j=3
i=4 j=5
结束i循环的第4次循环
结束i循环
可以用break,结束当前循环,跳出循环体
输出0--4之间的第一个偶数
for(int i=0;i<5;i++){
//判断i是偶数
if(i%2!=0){
//如果i不是偶数,则终止循环
break;
}
//输出i的值
System.out.println("i="+i);
}
在多重循环时,break默认终止当前循环
for(int i=0;i<5;i++){
for(int j=0;j<6;j++){
//当i==j时,终止j循环
if(i==j){
break;
}
System.out.println("i="+i+" j="+j);
}
System.out.println("结束i循环的第"+i+"次循环");
}
System.out.println("结束i循环");
输出结果:
结束i循环的第0次循环
i=1 j=0
结束i循环的第1次循环
i=2 j=0
i=2 j=1
结束i循环的第2次循环
i=3 j=0
i=3 j=1
i=3 j=2
结束i循环的第3次循环
i=4 j=0
i=4 j=1
i=4 j=2
i=4 j=3
结束i循环的第4次循环
结束i循环
loop1: for(int i=0;i<5;i++){
loop2: for(int j=0;j<6;j++){
//当i==j时,终止i循环
if(i==j){
break loop1;
}
System.out.println("i="+i+" j="+j);
}
System.out.println("结束i循环的第"+i+"次循环");
}
System.out.println("结束i循环");
输出结果:
结束i循环
数组是一组相同类型数据的集合,可以作为数据的容器使用,把多个数据集中存储
数组是引用类型(数组元素可以是基本数据类型也可以是引用类型),长度一经确定不能改变,在内存中连续分配,所以读取速度快
数组中存储的数据称为数组的元素
数组中元素的索引值从0开始
数组元素类型[ ] 变量名称;
或
数组元素类型 变量名称[ ] ;
例如:
int[] a; 或 int a[];
String[] s; 或 String s[]
初始化:
第一种:数组元素类型[ ] 变量名称=new 数组元素类型[数组长度];
第二种:数组元素类型[ ] 变量名称=new 数组元素类型[]{用逗号隔开元素的具体值};
第三种:数组元素类型[ ] 变量名称= {用逗号隔开元素的具体值};
//a1的长度为5,元素的值为默认值0
int[] a1=new int[5];
//a2的长度为3,元素的值为1,4,10
int[] a2=new int[]{1,4,10};
//a3的长度为4,元素的值为34,23,4,10
int[] a3={34,23,4,10};
在创建数组时一定要确认数组的长度,在初始化数组元素的时候同时初始化到内存中
使用 数组变量名.length可以返回数组的长度
int[] a1=new int[5];
int[] a2=new int[]{1,4,10};
int[] a3={34,23,4,10};
System.out.println("a1的长度:"+a1.length);
System.out.println("a2的长度:"+a2.length);
System.out.println("a3的长度:"+a3.length);
输出为:5、3、4
将数组元素一个一个取出来使用的过程叫做遍历
遍历数组需要用到循环控制,循环的次数用数组的长度控制
选择排序特点:查询次数较多,元素位置变换较少,比较适合易于查询而移动复杂的数据
冒泡排序
插入排序
数组元素类型[ ][ ] 变量名称=new 数组元素类型[一维长度] [二维长度]
一维二维长度都确定
//数组a中存储2个一维数组,每个一维数组的长度都是3
int[][] a=new int[2][3];
//对a中的数组元素可以继续赋值
a[0][0]=1;
a[0][1]=2;
a[0][2]=3;
a[1][0]=11;
a[1][1]=12;
a[1][2]=13;
只有一维长度确定
//数组b中存储2个一维数组,每个一维数组的长度不确定
int[][] b=new int[2][];
//对b中的数组元素可以继续赋值
b[0][0]=10;
b[0][1]=20;
b[1][0]=100;
b[1][1]=110;
b[1][2]=120;
b[1][3]=130;
静态类Arrays,定义了大量的sort方法,可以对数组中的元素进行排序,搜索,复制
equals():比较两个array是否相等。array拥有相同元素个数,且所有对应元素两两相等。
sort():用来对array进行排序。
binarySearch():在排好序的array中寻找元素。
Arrays.asList(array):将数组array转化为List (此种方法不正规)
int[] a=new int[]{12,3,90,1,2,10};
//使用API中的Arrays类的sort方法可以排序
Arrays.sort(a); //将数组a的元素升序排列
for(int x:a){
System.out.println(x);
}
使用final修饰的类,不能扩展,不能修改
一个字符串被创建后,他的值就不能被修改
String s1="Hello";
s1="World";
这里不是把Hello改为了World,而是重新分配空间存储World,S1的值发生了改变,指向新空间
为了能够重用这些不变的字符串,Java使用了字符串常量池;
凡是用=直接赋值的方式得到的字符串,都存储在常量池中;相同的共用一个具体字符串;
使用new创建的字符串不适用常量池,每次都分配新的内存空间;
String s2="Hello";
String s3="Hello";
String s4=new String("Hello");
String s5=new String("Hello");
验证:
String s2="Hello";
String s3="Hello";
String s4=new String("Hello");
String s5=new String("Hello");
System.out.println("s2==s3"+(s2==s3));
System.out.println("s4==s5"+(s4==s5));
System.out.println("s2==s4"+(s2==s4));
输出结果:
s2==s3 true
s4==s5 false
s2==s4 false
StringBuffer类,称为字符串缓冲区;所表示的也是一个字符序列;这个类型必须用new创建对象,和String相反,它是可变的类
StringBuffer sbf1=new StringBuffer ("Etc");
StringBuffer sbf2=new StringBuffer (" Java");
sbf1.append(sbf2);
System.out.println(sbf1);
输出结果为:Etc Java
证明:StringBuffer是一个可变的字符串类
三个类的区别
String类是不可变的,对象一旦被创建,就不能被修改;可以使用=直接赋值,此时使用常量池;也可以使用new创建,不使用常量池;
StringBuffer是可变的,对象创建后,可以修改;必须使用new关键字;
StringBuilder是不同步的,不考虑线程安全时,在多线程情况下使用比StringBuffer高效;必须使用new关键字;
有描述对象 以及对象之间关系的能力
面向对象的三大特征:封装、继承、多态
在Java中,万事万物皆对象
对象依赖于类存在(模板--个体实例)
在程序中应该使用的是对象
分析过程先有对象,后有类,开发过程,现有类后有对象
是描述对象的“基本原型”,它定义一种对象所能拥有的数据和能完成的操作
是程序的基本单元,最基本的类有一组结构化的数据和其上的一组操作构成
对象的行为是用调用的方法定义的
每个对象都保存着当前特征的信息--对象的状态,可能会改变,但并非自发
对象状态的改变必须通过调用方法实现,否则则说明封装性遭到破坏
封装使得对代码的修改更加安全和容易,将代码分成了一个个相对独立的单元,对代码访问控制得越严格,日后你对代码修改的自由就越大,可以很好的使用别人的类,不必关心其内部逻辑是如何实现的,让软件协同开发难度大大降低
对象的状态并不能完全描述一个对象,每个对象都有唯一的身份
作为一个对象的实例,每个对象的标识永远是不同的
状态常常也存在着差异,对象的这些关键特性在彼此之间影响着
类的基础声明
成员变量是类中特有属性的变量
在类中声明成员变量的格式,其类型可以是Java中任意的数据类型
class Bike{
int speed = 0 ; //新增加的成员变量
}
普通的成员属性取值在该类的 不同对象中不能被共享
不管在任何地方,引用类型都需要初始化后才可以使用,其初始值为null,代表不具备存储空间的内存空间,直接使用会造成程序运行异常
对象初始化时需要使用new运算符,从堆中分配内存,步骤是:
①说明新建对象所属的类名
②说明新建对象的名字
③用new为新建对象开辟空间
④创建对象的一般语法是:
⑤使用已经定义好的类,创建该类对象的过程叫做“实例化”
实例化类的对象之后,可以访问到类中的成员
对象名 .成员名
student.age = 18 ; //为成员属性赋值
public class StudentTest{
public static void main(String[] args){
Student student =new Student;
student.age = 18 ; //设置属性的值
System.out.println(Student.age); //读取属性的值
}
}
运行结果:18
成员方法是类中进行数据处理,实现相关功能的函数
方法决定了一个对象能够接收到什么样的信息,其基本组成包括:名称,参数,返回值和方法体
声明形式为:
返回类型可以是任意的Java数据类型,当一个方法不需要返回值时,返回类型为void。
Java中的方法只能作为类的一部分来创建
方法的特点:将功能代码进行封装;便于该功能进行复用;只有被调用时才会执行;提高代码的复用性;方法若没有返回值,则用关键字void表示,那么该方法中的return语句如果在最后一行可以省略不写;可以调用方法,不可以在方法内部定义方法;定义方法时,方法的结果应返回给调用者,交由调用者处理
return用法:
•代表“已经做完,离开此方法”
•如果此方法产生了一个值,这个值要放在return语句后面
class Bike {
int speed = 0;
void showSpeed() {
System.out.println(speed);
}
public void changeSpeed(int newSpeed){
speed = newSpeed ;
}
public static void main(String[] args){
Bike bike = new Bike();
//通过调用对象的方法来设置,获取属性的值
bike.changeSpeed(30);
bike.showSpeed();
}
}
输出结果:30
同一个类中的方法在本对象中调用其他方法直接使用方法名
class Bike {
int speed = 0;
void showSpeed() {
System.out.println(speed);
}
public void changeSpeed(int newSpeed)(int newSpeed){
changeAndShowSpeed(newSpeed) ;
showSpeed();
}
public static void main(String[] args){
Bike bike = new Bike();
//通过调用对象的方法来设置,获取属性的值
bike.changeSpeed(30);
bike.showSpeed();
}
}
第一个单词以小写字母开头,后面的单词则以大写字母来头
参数名称为一个单词时使参数的命名尽可能明确
可变API:在给定的既有内存上进行操作的API(Java字符串不存在任何的可变API)
不可变API:执行时需要分配一段内存后再执行操作的API(new)
参数只有值传递
基本数据类型和字符串传参时是值传递,其他对象传参是是引用传递的 (x)
public class ArgumentCallByValueTest {
public void changeSpeed(Bike bike,int newSpeed) { //Bike bike.int newSpeed是形参
bike.changeSpeed(newSpeed);
}
public static void main(String[] args) {
Bike bike = new Bike();
ArgumentCallByValueTest acbt = new ArgumentCallByValueTest();
acbt.changeSpeed(bike,20); //实参
bike.showSpeed();
}
}
形参就是一个普通的临时变量,位置特殊只是为了跳出方法体的作用域以便获取实参值(并非占位符)
方法体中的代码操作是形参变量,和实参无关
当方法中的形参在没有调用不可变API之前,形参的任何改变都将改变实参的状态,而当形参执行了任何不可变API之后,形参和实参就断开了这种状态联系