——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
1、标示符:程序中自定义的名词,比如说:类名,变量名,函数名,包名等。。
这些名字中的字符包含:数字:0~9;26个大小写字母;以及$和_。
注意:标示符定以时要遵循以下规则。
1.不能以数字开头。
2.不能使用关键字。
2、变量:内存中的存储空间,用来存储常量数据的。
开辟变量空间三要素:
1. 数据类型。
2. 变量名称。
3. 变量初始化值。
变量的好处:方便于运算,且变量空间可以重复使用。
那么什么时候定义变量呢?当有些数据不确定时,就定义变量。
既然变量时内存中的空间,那么它就有作用域和生命周期。
1.变量的作用域:从定义变量位置开始到该变量所在的一对大括号结束。
2.变量的生命周期:从定义变量开始到它所在的作用域结束。
3、常量:存储的是在程序中不会发生变化的数据。只能赋值一次,不可以被改变。
4、关键字:就是被java赋予特殊含义的单词。特点:所有字母都是小写。
保留字:还没有赋予特殊含义,但是打算在后期使用的单词。
那么关键字有哪些呢?
1. 用于定义数据类型的:
byte short char int long float double boolean void class interface
2、 用于定义数据类型值:
true false null
3、 用于定义流程控制的:
if else for do while switch break continue case return default
4、 用于定义访问权限修饰符:
private public protected
5、 用于修饰类、函数、变量的:
abstract static final synchronized
6、 用于定义类与类之间的:
Extends implements
7、 用于建立实例对象、引用实例和 判断实例:
new this super instanceof
8、 用于异常处理:
Try catch finally throw throws
9、 用于定义包和导入包的:
package import
10、 其他修饰符:
native strictfp transient volatile assert
5、数据类型:
1.基本数据类型:byte short char int long float double Boolean
2.引用数据类型:数组、类、接口。
整数默认类型是:int
小数默认类型是:double
级别(由小到大):byte short char 这三个同级。
int
float
long
double
自动类型转换 :从级别低到级别高的,系统自动转换。
强制类型转换:从级别高的到级别低的。就是把一个级别高的赋值给级别低的时候使用。
使用方法:(转换后的类型)转换前的类型;如:(byte)int类型
代码演示:
class Demo
{
//类型的自动和强制转换。
public static void main(String[] args)
{
byte b = 4;
short s = 3;
int d = 5;
d=b+s;//这是数据类型的自动转换。
//b=b+s;//这句代码会报错。错误: 不兼容的类型: 从int转换到byte可能会有损失。
//原因是因为b+s的结果为int类型的,不能自动转换成byte类型,
b=(byte)(b+s);//这就是数据类型的强制类型转换。
System.out.println(b);//结果为7.
System.out.println(d);//结果为7.
}
}
6、运算符号:
1.算数运算符:+ - * ++ – / %(取模:任何整数模2不是0就是1,这样可以用于开 关运算,只要改变被模数就可以。)
+:连接符。
++ –:分为两种情况。一种是在前,一种是在后。如:++a,a++.—a,a–.
2.赋值运算符:= += -= *= /= %=
3.比较运算符:< > == <= >= != 运算后的结果不是true就是false。
4.逻辑运算符:& | ! ^ && || 除了!外,其他的逻辑运算符连接的都是两个boolean型的表达式。
&: 两边都为true时,结果为true,否则false。
|: 两边都为false时,结果为false,否则为true。
^ (异或):和或有点不一样,两边都一样,结果为false。
两边结果不一样,结果为true。
& 和 && 的区别:
&:无论左边结果是什么,右边都参与运算。
&&(短路与):只要左边为false,那么右边就不参与运算。
| 和 || 的区别:
|:无论左边结果是什么,右边都参与运算。
||(短路或):只要左边为true,那么右边不参与运算。
5.位运算符:用于操作二进制位的运算符:
(右移) <<(左移) >>>(无符号右移)
例如:如何高效的算出:2*8. 2<<3.
例如:对两个变量的数据互换:要求不使用第三方变量。
int a=3,b=5;结果为:b=3,a=5;
一般解决办法(使用第三方变量):
int temp =0;
temp = a;
a = b;
b = temp;
不使用第三方变量:
利用加减原理:
a = a + b; a = 8;
b = a - b; b = 3;
a = a - b; a = 5;
异或原理:一个数异或另一个数两次,结果还是那个数。
a = a ^ b;
b = a ^ b;//b = a ^ b ^ b = a
a = a ^ b;//a = a ^ b ^ a = b;
代码演示:
需求:将一个整数装换成不同的进制,用函数的重载形式来完成。
public class JinZhiTrans
{
//这是一个空参数的构造函数,private的目的是不让改类创建实例对象。
private JinZhiTrans(){}
/**
这是将十进制转成二进制。
@param num 传入一个十进制的整数。
*/
public static void toBin(int num){
trans(num,1,1);
}
/*
十进制转八进制:
*/
/**
这是将十进制转成二进制。
@param num 传入一个十进制的整数。
*/
public static void toBa(int num){
trans(num,7,3);
}
/*
十进制转十六进制:
*/
/**
这是将十进制转成二进制。
@param num 传入一个十进制的整数。
*/
public static void toHex(int num){
trans(num,15,4);
}
/*
抽取出来的相同功能函数。定义成一个功能。
*/
private static void trans(int num,int base,int offset){
if (num==0){
System.out.println(num);
return ;
}
char[] ch={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[] arr= new char[32];
int pos = arr.length;
while (num!=0)
{
arr[--pos] = ch[num&base];
num = num >>>offset;
}
for (int i=pos;i<arr.length;i++ )
{
System.out.print(arr[i]);
}
}
}
7、语句。
1.用于循环的语句:
a)for循环。
b)while循环。
c)do while循环。
2.用于判断的语句。
a)if判断语句。
b)switch 选择判断语句。(当判断的是固定个数的时候建议用switch语句。效 率相对较高。)
3.这些语句的固定格式:
A)
for(初始化表达式;循环条件表达式;循环后的操作表达式){
执行语句;
}
B)
While(循环条件表达式){
执行语句;
}
C)
do{
执行语句;
}while(循环条件表达式)
D)
1.if(条件表达式){
执行语句;
}
2.if(条件表达式){
执行语句;
}else{
执行语句;
}
3.if(条件表达式){
执行语句;
}
else if(条件表达式){
执行语句;
}
……
else{
执行语句;
}
E)
switch(表达式){
case 取值1:
执行语句;
break;
case 取值2:
执行语句;
break;
……
default:
执行语句;
break;
}
对选择判断的说明:
用小括号中的变量字依次和case所对应的值进行比较,和哪个case所对应的值相等,就执行哪个case后的语句,如果没有和case所对应的值相同,则执行默认default下的语句。
switch代码演示:
需求:游戏俄罗斯方块,当出现不同的方块,调用不同的方块变形和旋转方法(具体变形和旋转的功能可以 不写),并要使用多线程来完成。
数值0时,是T型。
数字1时,是田型。
数字2时,是L型。
数字3时,是|型。
数字4时,是Z型。
import java.util.*;
class FangKDemo
{
public static void main(String[] args)
{
FangKuaiDemo fk = new FangKuaiDemo();//创建一个方块类的对象。
Thread t1 = new Thread(fk);//创建一个新线程。
Thread t2 = new Thread(fk);//创建一个新线程。
Thread t3 = new Thread(fk);//创建一个新线程。
Thread t4 = new Thread(fk);//创建一个新线程。
Thread t5 = new Thread(fk);//创建一个新线程。
t1.start();//启动一个线程。
t2.start();//启动一个线程。
t3.start();//启动一个线程。
t4.start();//启动一个线程。
t5.start();//启动一个线程。
}
}
//方块类。定义了产生不同方块的函数和对应的变形、旋转的函数,并集成Runnable接口,实现多线程。
class FangKuaiDemo implements Runnable
{
//产生不同方块的函数。
public static int FangKuai(){
//创建一个产生随机数对象。
Random d = new Random();
//产生0~4 这5个随机数。
return d.nextInt(5);
}
//T型方块变形和旋转的函数。
public static void t(){
System.out.println("我是 T 型,开始变形和旋转。");
}
//田型方块变形和旋转的函数。
public static void tian(){
System.out.println("我是 田 型,开始变形和旋转。");
}
//L型方块变形和旋转的函数。
public static void l(){
System.out.println("我是 L 型,开始变形和旋转。");
}
//|型方块变形和旋转的函数。
public static void shu(){
System.out.println("我是 | 型,开始变形和旋转。");
}
//Z型方块变形和旋转的函数。
public static void z(){
System.out.println("我是 Z 型,开始变形和旋转。");
}
public void run(){
for循环用来实现多次调用的功能。
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().getName());//获取执行该方法的线程名称。
//既然判断的次数是固定的,那么我们可以使用选择判断来实现该功能。
switch(FangKuai()){
case 0://返回的数值为0时,调用T型方块函数。
t();
break;
case 1://返回的数值为1时,调用田型方块函数。
tian();
break;
case 2://返回的数值为2时,调用L型方块函数。
l();
break;
case 3://返回的数值为3时,调用|型方块函数。
shu();
break;
case 4://返回的数值为4时,调用Z型方块函数。
z();
break;
default ://如果返回的数值不是0~4之间的,则就报异常.
throw new RuntimeException("程序运行错误。请检查!");
//这里可以不用写break,因为当执行到throw new RuntimeException("程序运行错误。请检查!")
//这句代码的时候程序就已经停止了,下面的代码根本不会被执行到。
}
}
}
}
注意:
1.break是可以省略的,如果省略了一个,则会一直执行 到下个break为止。
2.switch小括号里面的变量须为byte short int char四中类型中的一种。
3.default可以写在switch结构中的任意位置,但是如果放在结构中的第一行时,不管值是否和case的值相同,都会从default开始执行,直到执行到第一个break出现为止。
4.当判断的结果为boolean类型时,需要用if语句。
5.当某些语句需要被执行很多次时,需要用循环结构。
6.While和for可以互换:区别在于如需要定义变量用来控制循环次数,建议使用for循环,因为for循环结束后变量在内存中被释放。
7.break:用在循环和switch(选择判断)中,当单独存在时,下面不要定义其他语句,因为执行不到,编译会失败。当break在嵌套循环中时,跳出的只是当前循环,如果想要跳出外层循环,需要给外层循环做个标记即可。
8.continue:只能用于循环中,意思是结束本次循环,继续下次循环。当continue单独存在时,下面不可以定义其他语句,因为执行不到。
代码演示:
打印长方形时,外循环控制的是长方形的行数,内循环控制的是长方形的列数。
for (int x = 0;x<4 ;x++ )
{
for (int y = 0;y<3 ;y++ )
{
System.out.print("*");
}
System.out.println();
}
当打印的图形形状的尖朝上时。内循环的条件表达式是小于外循环的数值。
for (int x=0;x<5 ;x++ )
{
for (int y = 0;y<x ;y++ )
{
System.out.print("*");
}
System.out.println();
}
当打印的图形形状的尖朝下时。内循环的初始化值为外循环的值。
for (int x =0;x<5 ;x++ )
{
for (int y =x;y<5 ;y++ )
{
System.out.print("*");
}
System.out.println();
}
8、函数:完成一个功能往往需要一些代码来实现,而要再实现这个功能,则需要重复这些代码,为了提高代码复用性,则将这些代码定义成固定的功能,这个功能就是java中所谓的函数。
定义函数的格式:
修饰符 返回值类型 函数名称 (参数类型 形式参数1,参数类型 形式参数 2,参数类型 形式参数3 …… ){
执行语句;
return 返回值;
}
代码演示:
我们经常写的这个就是函数:
Public static void main(String[] args){
要执行的语句;
}
以上这个就是主函数。
主函数的作用:
1.保证该类的独立运行。
2.程序的入口。
3.被jvm调用。
注意:当函数没有具体的返回值时,返回值类型用void关键字表示,此时return语句可以省略不写,因为系统会自定加上。
return 的作用:结束函数,结束功能。
那么什么时候定义函数呢?
定义函数其实就是定义功能,定义一个函数就是实现一个功能。通过两个明确来完成。
1.明确该功能运算完的结果,就是在明确返回值类型。
2.明确该功能在运算时是否有未知内容参与运算,就是在明确该函数的参数列表(参数类型和参数个数)。
函数的作用:
1.定义功能。
2.封装代码,提高代码的复用性。
注意:函数中只能调用函数,不能定义函数。
那么为什么定义函数要定义函数名呢?
1.给功能做一个标示,方便于调用。
2.通过函数名称可以明确该函数的功能,方便于程序阅读。
注意:既然是定义函数,那么肯定会有重名的时候,那么怎么区分这些重名的函数呢?
通过函数参数的个数,或者参数的类型不同,通过这些来区分的。这种区分方法叫做函数的重载。
函数的重载只看参数列表和参数类型,和返回值类型无关。
函数重载形式代码演示:
class Demo{
pubic static void main(String[] args){
//下面的三个函数就是函数的重载形式。
//只是参数个数不同和参数类型不同。而函数名称则完全形同。
}
public static void printArr(int[] arr){
//取出数组中的各个元素。
for (int x =0;x<arr.length;x++){
//调用打印功能的函数。
sop("arr["+x+"]="+arr[x]+";");
}
}
public static void printArr(int[] arr1,int[] arr2){
for (int x =0;x<arr1.length;x++){
//调用打印功能的函数。
sop("arr["+x+"]="+arr1[x]+";");
}
for (int x =0;x<arr2.length;x++){
//调用打印功能的函数。
sop("arr["+x+"]="+arr2[x]+";");
}
}
public static void printArr(String[] arr){
System.out.println(arr);
}
}
代码演示简单的函数创建和调用:
class Demo
{
//创建一个数组,并取出数组中的各个元素。
public static void main(String[] args)
{
//创建一个int类型的数组。
int[] arr = new int[4];
//将元素存储到数组中。
arr[0] = 2;
arr[1] = 7;
arr[2] = 9;
arr[3] = 0;
//调用创建好的打印数组的函数。
printArr(arr);
}
//创建一个简单的打印功能的函数。
public static void sop(Object obj){
System.out.println(obj);
}
public static void printArr(int[] arr){
这里要注意的是:函数内只能调用函数,不能创建函数。
//取出数组中的各个元素。
for (int x =0;x<arr.length;x++){
//调用打印功能的函数。
sop("arr["+x+"]="+arr[x]+";");
}
}
}
9、数组。
数组就是一个容器,存储同一种数据类型的容器。用于封装数据,从0开始,是一个具体的实体。
创建数组的格式:
1.元素类型[] 数组名称 = new 元素类型[元素个数];
2.元素类型[] 数组名称 = new 元素类型[]{element1,element2,element3……};
3.元素类型 数组名称[] = new 元素类型[元素个数];
4.元素类型[] 数组名称 = {element1,element2,element3……};
代码简单演示数组的创建和取出数组中的元素:
class ArrayDemo
{
//要求:创建一个数组,并取出数组中的各个元素。
public static void main(String[] args)
{
//创建一个int类型的数组。
int[] arr = new int[4];
//将元素存储到数组中。
arr[0] = 2;
arr[1] = 7;
arr[2] = 9;
arr[3] = 0;
//取出数组中的各个元素。
for (int x =0;x<arr.length;x++){
System.out.println("arr["+x+"]="+arr[x]+";");
}
}
}
Java 内存空间分配情况:
1.寄存器 2.本地方法区 3. 方法区 4.堆 5.栈
在这里只做对栈和堆内存的分析。
栈:存储的都是局部变量(函数中定义的变量,函数上的参数,语句中变量),只要数 据运算完成,所在的区域结束,该数据就会被释放。
堆:用于存储数组和对象,也就是实体,每一个实体都有内存首地址值。
堆内存中的变量都有默认初始化值,因为数据类型不同,所以数值也就不同。
垃圾回收机制也存储在堆内存中。
10.设计模式
在java中有23种设计模式。
设计模式:解决问题最行之有效的思想。是经过人们反复使用、分类编排和代码设计经验的总结。
使用设计模式,就是为了使代码更容易被比人理解,提高代码的重用性,保证代码的安全性。
1、单例设计模式:保证一个类在内存中,只有一个对象(既是对象唯一性)。就是解决这对象唯一性这一类问题的。
如:Runtime()方法就是使用单例设计模式来设计的。还比如:多线程读取一个配置文件时,这时就建议将配置文件封装成对象,而这个对象就需要在内存中保证它的唯一性。
那么在Java中又是怎么用代码保证对象的唯一性的呢?
思想:
1. 不让其他程序创建该类对象。
2. 在本类中创建一个本类对象。
3. 对外提供方法,让其他程序获取这个对象。
代码体现:
1. 私有化构造函数。
2. 创建私有并静态的本类对象。
3. 定义共有并静态的方法,获取这个对象。
步骤:
1.因为每一对象的创建都需要构造函数的初始化,所以只要将构造函数私有化就可以了,其他程序就无法在创建该对象了。
2.在该类中创建一个本类对象。
3.定义一个方法,来返回该对象。让其他程序都可以通过这个方法来获取到该对象(作用:可控)。
创建单例设计模式有两种方式:
1.饿汉式:就是类一加载就创建好了本类对象。
代码:
class SingleDemo1
{
private SingleDemo1(){}//私有化构造函数。
private static SingleDemo1 s = new SingleDemo1();//类一加载,就创建静态并私有的本类对象。
public static getSingle(){//对外提供静态并共有的方法,来获取到这个本类对象。
return s;
}
}
2.懒汉式:类加载时不创建该类对象,什么时候使用,什么时候创建该类对象。又叫延迟加载。
代码:
class SingleDemo2
{
private SingleDemo2(){}//私有化构造函数。
private static SingleDemo2 s = null;//创建私有并静态的本类对象引用。
public static getSingle(){//对外提供静态并共有的方法,来获取这个本类对象。
if(s==null)//判断本类对象的引用是否有实体指向。
s = new SingleDemo2();//把创建本类对象的地址值赋值给本类对象的引用。
return s;//如果本类对象的引用不为null,则直接返回本类对象。
}
}
2、 模版设计模式:当功能内部一部分实现确定,一部分不确定。这时可以把不确定部分暴漏出去,让子类去实现。
在这里举一个例子来说明模版设计模式。
需求:要求计算出执行某一段代码的时间。代码是不确定的。
代码:
//模版设计模式:
abstract class MoBan
{
public final void getTime(){
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
System.out.println("这段代码运行了:"+(end-start)+"毫秒。");
}
public abstract void code();//这部分代码是不确定的,所以是抽线抽象方法,需要被子类来实现。
}
class CodeDemo extends MoBan
{
public static void main(String[] args){
CodeDemo cd = new CodeDemo();//创建子类对象。
cd.getTime();//调用父类中的getTime方法。
}
public void code(){//继承模版抽象类,并复写code方法。
for (int x =0 ;x<200 ;x++ )
{
System.out.println(x);
}
}
}
——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-