Java(SE)基础知识

目录

初始Java程序——

标识符和关键词

关键字

标识符

基本数据类型

占用空间和取值范围

字符类常量的表示方式

变量

数据的输入和输出(☆☆☆☆)

一.常用格式控制符及其含义

二.基本输入语句

三.基本输出格式

表达式与运算符

算术运算符——

⑴对于“++” 和“--”

⑵对于除法和取余

⑶字符型数据的运算

关系运算符——

逻辑运算符——

其他运算符与表达式——

1.条件运算符与条件表达式

2.位运算符

3.复合赋值运算符

算术符的优先级

判断与循环

㈠if语句

㈡for循环

范例:当输入一个数,计算该数的阶乘.

㈢ while循环与Do-while循环

㈣switch 语句实现多分支结构

范例——

㈤ break与continue语句

方法

⑴void方法的定义和调用

(2)含return语句和参数的定义与使用

范例—— 编辑

(3)方法的嵌套调用

(4)方法的递归调用 (☆☆☆)

数组

一.一维数组

Ⅰ.声明

Ⅱ. 数组的建立 要想真正地存储数据,不仅仅通过声明给出数组名称和可存放数据的类型,更要为其分配内存空间,即创建数组.

Ⅲ.一维数组的初始化

Ⅳ. 一维数组的访问

范例——

一维数组的排序和查找

❶排序


初始Java程序——

Java代码主要可在IntellJ IdeaEclipse这两款使用Java语言开发的工具软件中输入.

简易框架为:

public class <文件名> {
    publicstaticvoidmain(String args[]){
         System.out.println("Java欢迎您!");
    }
}

注:二行中,main是方法名,public、static分别表明main()方法是公共、静态的方法,而void表示main()方法没有返回值;对于String args[],其定义了一个数组args作为main()的参数.


而在JDK(应用插件)1.5版本开始,Java增加了Scanner类,为数据输入带来了极大的方便;这将会在后续内容中提到。

故对于Java的基础框架我们应当更新为如下图——

import java.util.Scanner;

public class <文件名> {

   publicstatic vodi main(String args[]) {

       Scanner <Scanner对象>=newScanner(System.in);
      
       byte/short/int/long/float/double/boolean x;
       
       ...
      
       System.out.printf("%d/f/s/c/...",&x);
      
   }
  
}   

标识符和关键词

关键字

定义:具有特定含义的字符,如public、class、void、int、double等等.

常见Java关键字——

boolean

byte

break

case

char

class

continue

default

do

double

else

float

for

if

import

int

long

new

package

private

public

return

short

static

switch

void

while


标识符

变量需要一字,变量的名字是一种“标识符”,意思是它是用来识别不同的名字

标识符有独特的构造规则。基本的原则是:

  • 标识符只能由英文(A~Za~z)、数字、汉字、“$”和下划线“_”组成,数字不能出现在第一个位置上

  • 毋庸置疑的,标识符绝不能与关键字同名!!

  • 与C/C++相同,Java的标识符是区分大小写的,例如Name与name是两种不同的标识符;

  • 此外,为了增强用户的可读性,自主命名的标识符应当做到“见名知义”;

在Java中,大部分情况下标识符可使用骆驼法则,即单词之间不使用特殊符号分割,而是通过首字母大写来分割.

比如:SupplierName,addNewContract,而不是supplier_name,add_new_comtract. 类名的首字母通常采用大写方法名、参数名局部变量名的首字母通常采用小写.

基本数据类型

Java语言常常被划分为整型浮点型字符型布尔型四大类.

Ⅰ.整型( byteshortintlong

占用空间和取值范围——

byte 1字节 -2^7 ~ (2^7-1)

short 2字节 -2^15 ~(2^15-1)

int 4字节 -2^31 ~ (2^31-1)

long 8字节 -2^63 ~ (3-2^63-1)


常量

十进制整型常量—— 与日常阿拉伯数字的写法相同,即第一个数字不能为0

八进制整形常量——主要由正、负号和0~7组成, 第一个数字必须是0

十六进制整型常量——主要由正、负号和0~9、 a~f或A~F组成, 有前缀0x

二进制整型常量——主要由正、负号和0、1组成, 有前缀0b(或者0B)

对于整型常量的类型的判断,我们首先根据其后的后缀进行判断,后缀1和L表示是long型常量,如-321、2L;若没有出现后缀,则通过常量的数值大小进行判断,如0、127为byte型,128、32767是short型,32768、2147483647是int型, 而2147483648必须表示为2147483648L.
Ⅱ.浮点型 (float;double)


占用空间和取值范围

float 4字节 -3.402826×10^38~3.402826×10^38 6位有效数字

double 8字节 -1.797693×10^308~1.797693×10^308 15位有效数字

常量

十进制小数形式——由数字和小数组成,与日常阿拉伯数字的写法相同

指数形式——类似于科学计数法,通常用于表示绝对值非常小或非常大的值。它由正、负号、数字和字母e(E)来表示,其中E是指数的标志,其后连接的数字表示是10的幂次方,如1625.0<==>1.625E3,0.00731<==>7.31E-3;注意, E之后的数据必须是 整数 !!!!!

浮点型常量 默认情况下是 double类型,也可以在数字后附加后缀d或D来表示double类型;同理,若要表示float类型常量,可以在数字后面附加后缀f或F.
Ⅲ.字符型(char)
字符型用于表示单个字母、数字字符、标点符号和其他特殊字符。在计算机内部我们采用 编码的方式表示字符,其中每个字符型数据一般占用2字节,即16个二进制位。一个汉字一般可表示为一个字符型数据,即占用2字节。
Java语言使用编码方案 Unicode码。
包含 多个字符的姓名、地址等数据称为 一个字符串,而在Java中字符串的表示超出了其基本数据类型的范畴,需要引入其他方式来表示!

字符类常量的表示方式——

字符型常量由 单引号‘ ’)括起的单个字符,例如'a','6','M','&','个';显然,字符常量只能是一个字符,如'XY'是非法的.

切不可将双引号和单引号混为一谈,单引号表示一个字符,而双引号表示一个字符串.

(☆☆)对于特殊字符,它们可能并无字符,我们需要采用 转义字符 来表达
Ⅵ.布尔型(boolean)
布尔型是逻辑类型,用于表示" "或" "状态的数据类型,对应两种取值—— true/ false,其中表达条件的表达式都是布尔型的数据.


变量

  1. 变量的声明

基本形式与Visual Basic,C/C++相同,标准格式为:

数据类型 变量名表 ( 如下图所示 )

int k=5;
    
    char='*';
   
    double area;
   
    int a,b=0;

2.变量的初始化

如果上图的变量声明结束后直接书输入表达式进行计算,则会出现语法错误!

在Java语言中规定,在声明变量时必须对变量进行初始化操作!!!若变量从未被初始化,则不可以执行获取变量值的操作!


数据的输入和输出(☆☆☆☆)

一.常用格式控制符及其含义

二.基本输入语句

在JDK1.5版本后增加的Scanner类后,我们可以灵活地运用Scanner类进行键盘输入

Scanner类的主要方法——

方法

功能描述

next();

读取一个字符串,读到空格,Tab键或Enter键结束

nextLine();

读取一行包括空格和Tab键),只有Enter键才结束

nextByte();

读取一字节

nextShort();

读取一个短整型

nextInt();

读取一个整型

nextLong();

读取一个长整型

nextFloat();

读取一个float型

nextDouble();

读取一个double型

PS:上述表格所示,大小写必须区分!

标准格式: Scanner <input> = new Scanner (System.in);

......

byte/.../double m;

m=<input>.nextByte/.../nextDouble();

三.基本输出格式

标准格式为: System.out.printf(“格式控制字符串”,表达式1,表达式2,......);/

System.out.println(“格式控制字符串”,表达式1,表达式2,......);

ⅰ. 整型数据的格式控制

  • 正常语句为

int a=2,b=3;

System.out.printf("a=%d,b=%d",a,b);

则输出为“a=2,b=3”;

  • 实际上在整型数据的格式控制中,我们还可以控制输出宽度,例:

int a=2,b=325;

System.out.printf("a=%5d,b=%2d",a,b);

则输出为“a= 2,b=325”;

其中“%5d”用以指定a的值以十进制的整数形式输出,且宽度是5,若a的实际位数小于5,故左边补四个空格;而b的实际位数大于2则反之,不得补空格.

ⅱ.实型数据的格式控制

对于实型数据的格式控制共有“%e”和“%f”两种,分别是以科学记数法和小数形式输出实型数据

  • 实型数据的输出,小数点后面总是输出6位!

  • 当实际小数位数小于6位时,末尾会补“0”至6位;而当超出6位时,会进行四舍五入的处理!

  • 例1:

System.out.printf("e=%f,pi=%f",2.718,3.1415926);

则输出为“2.718000,3.141593”;

  • (☆☆)例2:

System.out.printf("%.2f",2.718);

则输出为“2.72”.在%e或%f之间加入“.”后面连接一个整数x,则可调整输出小数的位数

  • 例3:

System.out.prtintf("%7e",2.718);

则输出为“ 2.718”;在%e或%f之间加入整数x,可实现输出的数据总宽度;如上图所示,2.718所占的总宽度为5,而设置的总宽度为7,故输出会空出2格.

  • 例4(例2+例3):

System.out.printf("%7.2f",2.718);

则输出为“ 2.72”;在%e或%f之间先加入整数x控制总宽度,再加入“.”后面连接一个整数y控制小数的位数.

ⅲ.布尔型数据的格式控制

布尔型数据的格式控制是%b.

boolean flag=true;

System.out.printf("%b",flag);

ⅳ.字符型数据的格式控制

字符型数据的格式控制是%c.

char ch='a';

System.out.printf("%c,%c",ch,ch-32);

将输出"a,A".

ⅴ.

格式控制字符还可以与各种标志搭配组合在一起,形成更丰富的输出格式.

标志

说明

实例

结果

+

为正数或负号添加符号

("%+d",15)

+15

-

左对齐

("%-5d",15)

15

0

数字前面补0

("%04d",99)

0099

以“,”对数字分组

("%,f",9999.99)

9,999.990000

使用括号包含负数

("%(f",-99.99)

(99.990000)


表达式与运算符

运算符分为算术运算符、关系运算符和逻辑运算符;同理,表达式分为算术表达式关系表达式逻辑表达式.

算术运算符——

双目运算符

Java符号

意义

+

+

-

-

×

*

÷

/

%

取余

()

()

括号

单目运算符

C符号

意义

+

+

取正

-

-

取负

+1

++

自增

-1

--

自负

⑴对于“++” 和“--”

含义:

❶如果是对于同一个变量进行自增或自减处理,则结果没有差别。

int a=0;

1.a++

2.a--

无论是情况1还是2,最终的结果均为 1.

❷如果自增/自减运算符与其他运算符(两个变量)组合使用,则运算符放在左侧和右侧对执行结果有影响.

例一:

int a=0,b=0;

a=2*b++;

最终结果为“a=0,b=1”;执行过程是,先将b的值(0)乘以2并把乘积(0)赋值给a,这样a的值即为0,最后再执行b自增的操作,则b的值为1.

例二:

int a=0,b=0;

a=2*++b;

最终结果为“a=2,b=1”;执行过程是,先将b的值加1,则b的值为1,然后将b的值(1)与2的乘积(2)赋值给a,这样a的值即为2.

(总结:b++是先执行程序再自增,而++b则为先自增再执行程序)

例三:

itn a=0,b=0,c=0;

a=b--;

c=--b;

显然,由上述规律可知,a=0,b=-2,c=-2.

注:自增运算和自减运算的运算对象只能是单一变量绝不能是常量与表达式!!!(如“8++”与“(a+b)--”都是错误的输入)

⑵对于除法和取余

Ⅰ.除法(/)

若除法运算的除数和被除数都是整数,则按照整除的规则进行;而若有一个数为浮点数,则按照浮点数除法的规则进行,即必须将被除数或除数改为浮点数

如对于表达式“159/10=15.9”而言,我们可以采取以下多种方式——

Ⅰ   System.out.printf("%.1f",159.0/10);

Ⅱ   System.out.printf("%.1f",159/10.0);

Ⅲ   double a=18.0;
    
     System.out.printf("%f",a/10);

Ⅳ   double a=10.0;

     System.out.printf("%f",159/a)

Ⅴ   double a=159.0,b=10.0;
    
     System.out.printf("%f",a/b);


Ⅶ   int a=159;

     System.out.printf("%f",a*1.0/10);

Ⅷ   int a=10;

     System.out.printf("%f",159/(a*1.0));

Ⅱ.取余(%)

(☆)参与取余运算的两个数必须是整型数据

⑶字符型数据的运算

实际上形同整型和浮点型数据的运算,字符型数据的运算参与的也是整型数据,也就是字符所对应的编码值.

例如,字符‘a’的编码值为97,故表达式‘a’+3的值为100.


关系运算符——

常用于判断条件的语句中

编辑 注:(☆☆)切勿将“==”写作“=” ,前者是关系运算符,后者是赋值运算符


逻辑运算符——

(☆)逻辑运算是对逻辑量(True【1】和False【0】)的运算

运算符

含义

实例

结果

逻辑“非”

!a

true→false;反之亦然

&&

逻辑“与”

a&&b

1*1=1;1*0=0;0*0=0

||

逻辑“或”

a||b

1+0=1;1+1=1;0+0=0

优先级——非(!)>与(&&)>或(||)

例:判断年份不是闰年.

import java.util.Scanner;

classMain(){
   
   publicstaticvoidmain(Srting arg[]){
       
         Scanner input=newScanner (System.in);

         int year=k.nextInt();

         boolean flag;

         if (!(year%4==0&&$year%100!=0||year%400==0){
 
                flag=true;
       
         else flag=false;

         System.out.printf("%b",flag);
   
         }

   }

}

另外,在逻辑运算中对于Boolean类型也可以输出相应的数值,其中true--1,flase--0

boolean b=6>(<)5;

System.out.printf("%d\n",b);

其输出值即为1(0)


其他运算符与表达式——

1.条件运算符与条件表达式

条件运算符将3个表达式组合在一起,组成条件表达式,其一般形式为:

表达式1?表达式2:表达式3(意思为先计算表达式1的值,如果它的值为 true,将 表达式2的值作为条件表达式的值;否则,将 表达式3的值作为条件表达式的值)

例:x=a>b?a:b; //将a和b的最大值赋给x

y=x>0?x:-x; //将x的绝对值赋给y

2.位运算符

位运算符适用于整型的运算对象,运算特点是以二进制为单位进行,如下表所示.

运算符

名称

含义

示例

&

按位与

两位同时为1,结果为1,否则为0

0&0=0;0&1=0;1&0=0;1&1=1

5&9的值为1

|

按位或

两位同时为0,结果为0,否则为1

0|0=0;0|1=1;1|0=1;1|1=1

5|9的值为13

~

按位取反

按位取反,即将0变为1,1变为0

~5的值为-6

^

按位异或

0^0=0;0^1=1;1^0=1;1^1=0

两位不同,结果为1,否则为0

5^9的值为12

>>

向左移位

将运算对象的二进制码整体左移指定位

15>>2的值为3

<<

向右移位

将运算对象的二进制码整体右移指定位

15<<2的值为60

3.复合赋值运算符

复合赋值:五个算术运算符(+ - * / %)可以和赋值运算符“=”结合起来,形成复合赋值运算符——“+=”“-=”“*=”“/=”“%=”

(注意两个运算符中间绝对不能有空格)

●total+=5 ⇒total=total+5

●total+=(sum+100)/2 ⇒total=total+(sum+100)/2

(☆)●total*=sum+12 ⇒total=total*(sum+12)


算术符的优先级

(☆)总结论:算术运算符>关系运算符>赋值运算符

运算符的优先级与结合性:

优先级

运算符

名称

结合性

1

.

从左到右

( )

圆括号

从左到右

[]

方括号

从左到右

2

+

正号

从右到左

-

负号

从右到左

++

自增

从右到左

--

自减

从右到左

~

按位非

从右到左

逻辑非

从右到左

3

*

从左往右

/

从左往右

%

取余

从左往右

4

+

从左往右

-

从左往右

5

<<

左位移运算符

从左到右

>>

带符号右移运算符

从左到右

>>>

无符号右移

从左到右

6

<

小于

从左到右

<=

小于或等于

从左到右

>

大于

从左到右

>=

大于或等于

从左到右

7

==

等于

从左到右

!=

不等于

从左到右

8

&

按位与

从左到右

9

|

按位或

从左到右

10

^

按位异或

从左到右

11

&&

逻辑与

从左到右

12

||

逻辑或

从左到右

13

?:

条件运算符

从右到左

14

=

混合运算符

从右到左

+=

-=

*=

/=

%=

......

当优先级数字越小表示优先级越高!!!


判断与循环

㈠if语句

一个基本的if语句由一个关键字if开头,跟上在括号里的一 个表示条件的逻辑表达式(注:不加分号!!!),然后是 一对大括号“{}”之间的若干条语句。

标准格式:if(<判断条件>){ ...}

如果表示条件的逻辑表达式的结果不为0,那么就执行后面 跟着的这对 大括号内的语句,否则就跳过这些语句不执行, 而继续下面的其他语句。

例:if (total>amount)total+=amount+5; if语句后面也可以不用大括号“{}”,但是一定要读懂加不加大括号的区别! 范例⒈:

Scanner k=newScanner(System.in);

System.out.printf("请输入成绩");

Const pass=60;

int score;

while(k.hasNextInt()){

  k.nextInt();

  if (score>pass) 

    System.out.printf("通过");

  else 
    
    System.out.printf("未通过");
  
    System.out.printf("再见");
    
    break;
  }

当不加入{}后若满足条件只实行下一行代码;而据此,此代码显然违背了该程序设计的初衷,因为当else后面没有加入{}时,将会依次实行,即每次都会输出“再见”且一次即实行“break”退出!

⒉.应当修改为——

Scanner k=newScanner(System.in);

System.out.printf("请输入成绩");

Const pass=60;

int score;

while(k.hasNextInt()){

  k.nextInt();

  if (score>pass){
    
    System.out.printf("通过");
    
  }                 

  else{}
    
    System.out.printf("未通过");
  
    System.out.printf("再见");
    
    break;
  }
 
}

㈡for循环

for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步进行调整,比如加1或者减1

(☆☆)for循环标准格式

for(<变量初始值>;<循环限制条件>;<递增递减变量>){……}

例:for(i=1;i<=n;i++){}

或:int i=1;…for(i;i<=n;i++){}(注:当for嵌套在一个大循环内时,第二次进行for循环时需重新赋i=1

范例:当输入一个数,计算该数的阶乘.

Scanner k=newScanner(System.in);

System.out.printf("请输入成绩");

int m;

m=k.nextInt();

int sum=1;

  for (int i=0;i<n;i++){

  sum*=i+1;

  }
  
  System.out.printf("%d",sum);

其中,对于for循环内的三个表达式,其实可以进行位置迁移,但两个分号必须保留!

for (i=1;i<=n;i++){
   ...;
}
i=1;
for (;i<=n;){
   ...;
   i++;
}

上两者完全等价,甚至完全可以表示为如下情况——

i=1;
for ( ; ; ){
   ...;
   i++;
   if (i>n) break;
}

虽然但是,完整的for语句显然更加清晰明了.


㈢ while循环与Do-while循环

编辑

编辑

易知,两者区别在于Do-while循环体执行结束的时候才来判断条件!无论如何,循环都会执行至少一遍,然后再来判断条件。

与while循环相同的是,条件满足时执行循环,条件不满足时结束循环

两者格式——

(While循环) while(<循环条件>){

<循环体条件>}

(Do-while循环) do {

<循环体语句>

}while(<循环条件>)(注意分号!!!)

显然,dowhile语句在进入循环的时候并不做检查,而是在执行完一轮循环的代码后再来检查循环的条件是否满足,如果满足则再次进行循环,反之则结束循环.


㈣switch 语句实现多分支结构

一般格式为:

switch (表达式A){

case 常量表达式1:语句序列1;break;

case 常量表达式2:语句序列2;break;

case 常量表达式3:语句序列3;break;

......

case 常量表达式n:语句序列n;break;

default:语句序列n+1;

}

Ⅰ.用此语句主要用于节省计算时间,不同于if语句的逐句判断,在switch语句中表达式A会在下面的case里找到相应的语句直接跳转

Ⅱ.表达式A的数据类型可以是byte,short,int或char,但是不可以是long,float,double和boolean.

Ⅲ.每个case后面必须是常量表达式而不能是变量;每个case后面的值必须不同,否则会出现相互矛盾的现象.

Ⅳ.从形式上讲,break语句并不是必要的,但是当删去break语句后,程序可能会发生变化;例如,当把语句序列2后面的break语句删除,那么当表达式A的值与常量表达式2得我值相等时,不仅会执行语句序列2,还会执行其后的语句,一直执行遇到break为止,也仅有执行语句2之前有直接跳转的迅捷功能.

范例——

输入一个百分制的成绩t,将其转换成对应的等级,具体转换规则如下:

90~100为A;

80~89为B;

70~79为C;

60~69为D;

0~59为E;

输入数据有多组,每组占一行,由一个整数组成。

对于每组输入数据,输出一行。如果输入数据不在0~100范围内,请输出一行:“Score is error!”。

import java.util.Scanner
classMain{
  publicstaticvoidmain(String args[]){
    Scanner k=newScanner(System.in);
      while(k.hasNextHas()){
	  grade=score/10;
	  if (score>100&&score<110) {
       grade=11;}
      switch(grade){
        case10: printf("A\n");
	    break;
        case9: printf("A\n");
        break;
        case8: printf("B\n");
        break;
        case7: printf("C\n");
        break;
        case6: printf("D\n");
        break;
        case5: printf("E\n");
        break;
        case4: printf("E\n");
        break;
        case3: printf("E\n");
        break; 
        case2: printf("E\n");
        break;   
        case1: printf("E\n");
        break;  
        case0: printf("E\n");
        break;
        default: printf("Score is error!\n");}
        }
  }
}

㈤ break与continue语句

最大区别:continue语句只结束本次循环,不终止整个循环的执行;而break语句则是结束整个循环过程.

特别提醒,若在多个嵌套结构内使用break,则跳出的仅仅是一个内嵌套循环


方法

在Java程序段内,我们可以通过一些静态方法的定义和调用来解决大型问题;一般采用分而治之的方式,将程序分解成若干个子问题,然后用比较小的程序模块解决这些子问题,从而增强程序结构的清晰度,提高编程效率.

⑴void方法的定义和调用

当一个方法没有数据(没有具体返回值)需要传输给调用者时,我们一般使用返回值的类型为void.最终返回的大多是一条输出语句!

范例:——

public class Main{
  public static void main(Srting args[]{
     System.out.printf("18!=");
     fact();
     System.out.printf("bye.\n);
  }
  static void fact(){
     double f=1;
     for (int i=1;i<=18;i++){
        f=f*i;
     }
     System.out.printf("%.0f\n",f);
  }
}

上述定义了一个没有返回值、只有输出语句的static void fact()方法;程序从main()方法的第一条语句开始执行,遇到调用方法语句“fact();”时,即转去执行方法中的语句序列,执行完后再回到main()方法,执行后面的输出语句.


(2)含return语句和参数的定义与使用

return语句用于将方法中的数据传递给调用者,当在执行方法体中的语句时,一旦遇到return语句,便立即结束方法的执行,并把return语句后的表达式的值(具体值)传递给调用者.

标准格式(☆☆☆)

import java.util.Scanner;
public class <左上角文件名>{
  publicstaticvoidmain(String args[]){//主程序
    Scanner <input>=newScanner(System.in>;
    ...
    ...
  }
  static <数据类型> <自定义方法名>(<数据类型><变量1>(,<数据类型><变量>)){//分程序
    <数据类型><变量*>;
    <数据类型><变量>;
    ...
    ...//表达式中必须含有声明里的变量1return <变量*>;//最终只能输出一个变量作为输出值传递给主程序
  }
}

     
    

范例——

编辑

分析,对于上述例题,我们应当定义三个带参数的方法(用return返回具体值)放入主程序中用于增强编程效率.

import java.util.Scanner;

public class Triangle{
    public static void main(String args[]) {
            Scannerk=newScanner(System.in);
            double a=k.nextdouble ();
            double b=k.nextdouble ();
            double c=k.nextdouble ();
            boolean flag=IsLegal(a,b,c);
            if (flag==true){
                 double area,perimeter;
                 area =getArea(a,b,c);
                 perimeter =get Perimeter(a,b,c);
           }
    }
     static double getArea(double a,double b,double c){
        Double p=(a+b+c)/2;
        double p1,p2,p3;
        p1=p-a;
        p2=p-b;
        p3=p-c;
        double sum=p*p1*p2*p3;
        double num=Main.pow(sum,0.5);
        return num;
   }  
    static double get Perimeter(double a,double b,double c){
       int sum=a+b+c;
       return sum;
   }
    static boolean isLegal(double a,double b,double c){ 
       boolean flag;
       if (a+b>c&&a+c>b&&b+c>a&&a-b<c&&b-a<c&&a-c<b&&c-a<b&&b-c<a&&c-b<a){
       flag=true;
       }else {
            flag =false;
        }
        return flag;
   }
}

(3)方法的嵌套调用

定义:如果A方法中调用了B方法,而B方法中又调用了C方法,这样的调用关系称为方法的嵌套调用.

例:

import java.util.Scanner;
publicclassMain{
  staticdoublefact(int n){
     double f=1;
     for(int i=1;i<=n;i++){
        f*=i;
     }
  return f;
}
  staticdoublecomb(int m,int n){
    return fact(m)/fact(n)/fact(m-n);
  }
  publicstaticvoidmain(String args[]){
     Scanner k=newScanner(System.in);
     int m,n;
     m=k.nextInt();
     n=k.nextInt();
     System.out.printf(".0f",comb(m,n));
  }
}

(4)方法的递归调用 (☆☆☆)

可以近似的看作在方法体内间接包含了对本方法的调用,如A方法调用了B方法,而B方法又调用了A方法,递归方法的优点在于可以使程序更加简洁.

而在递归调用时为防止其无限地进行下去,必须在函数内设置递归调用终止的条件。此时,当条件满足终止条件时,程序就不再递归调用,而是逐层返回,一一计算.

实例——计算阶乘的递归方法.

import java.util.Scanner;
publicclassMain(){
  publicstaticvoidmain(String args[]){
    Scanner kp=newScanner(System.in);
    int n=kp.nextInt();
    System.out.printf("%d",fac(n));
  }
  staticlongfac(int n){
    if (n==0||n==1){
       return1;
    }
    else{
       return fac(n-1)*n;
    }
  }
}

编辑


数组

在很多情况下,我们需要将一组固定数目、类型相同的数据组织在一起处理,此时最直观的解决办法是,定义一组同名并有下标的组别将各个数字储存起来,我们将之称为数组.

一.一维数组

Ⅰ.声明

格式为—— <数组元素类型> [ ] <数组名>

例:int [] a;

double [] b;

boolean [] c;

Ⅱ. 数组的建立 要想真正地存储数据,不仅仅通过声明给出数组名称和可存放数据的类型,更要为其分配内存空间,即创建数组.

格式为—— <数组名>=new <数组元素类型> [数组长度]

例:a=new int [100];

b=new double [50];

c=new boolean[20];

同时,也可以对 Ⅰ 、Ⅱ 合二为一,其☆☆☆☆)标准格式为——

<数组元素类型> [ ] <数组名>=new <数组元素类型> [数组长度] 即 :

int []a=new int [100]; double []b=new double[50]; boolean []c=new boolean[20];

Ⅲ.一维数组的初始化

数组创建以后,与单个变量需要自行初始化不同, 系统会为每个数组分配一个初始值;如int类型为0,float或double类型为0.0,char类型为‘\0’,boolean类型为false.

对于数组的初始化,我们可以采取以下两种方式(即在上述Ⅰ.和Ⅰ + Ⅱ两种情况下)

int []a={5,16,9,63};

或

int []a=newint[]{5,16,9,63};

注:初始化数组时在花括号内用“,”隔开,此时数组的大小由花括号中的用于初始化数组的元素个数决定;与此同时,在初始化时切勿在数组声明中指定数组的大小,否则会引起编译错误!(如 int )

Ⅳ. 一维数组的访问

数组元素通常通过下标来访问. 一般形式为:<数组名>.length

例如,若有如下的数组定义:

a=newint[20];

b=newdouble[10];

则a.length、b.length的值分别为20和10.

范例——

输入一个班10名学生的数学成绩,求这10名学生的平均数学成绩.

import java.util.Scanner;
publicclassMain{
  publicstaticvoidmain(String[] args){
    Scanner k=newScanner(System.in);
    double [] a=newdouble[10];
    double sum=0;
    for (int i=0;i<a.length;i++){
      a[i]=k.nextDouble();
    }
    for (int i=0;i<a.length;i++){
      sum+=a[i];
    }
    System.out.printf(sum/a.length);
  }
}

然而,在Java 5出现了全新的foreach语句,尤其在遍历数组、集合方面,foreach为开发人员提供了极大的方便!

在Java内部,foreach是完全实现了for循环用于遍历数组中的每一项.

(PS:数组必须已经被定义完,即foreach语句的使用应在定义数组之后

语法格式——

for(元素类型 t 元素变量 x:遍历对象 obj ){

引用了x的Java语句;

}

对于上述的求平均值的题目,可以修改为:

import java.util.Scanner;
publicclassMain{
  publicstaticvoidmain(String[] args){
    Scanner k=newScanner(System.in);
    double [] a=newdouble[10];
    double sum=0;
    for (int i=0;i<a.length;i++){
      a[i]=k.nextDouble();
    }
    for (double x:a){
      sum+=a[i];
    }
    System.out.printf(sum/a.length);
  }
}

诚然,foreach语句是for循环的特殊简化版本,但是foreach语句并不能完全取代for语句。如果要引用数组或者集合的索引,foreach语句无法做到,foreach能老老实实地遍历数组或者集合一遍!


一维数组的排序和查找

❶排序

1.选择排序——

经典原始代码(实现从小到大的有序数组的排列)

for (int i=0;i<a.length;i++){
   int k=i;//假定第一个数组a[i]为最小值for (int m=k+1;m<a.length;m++){
      if (a[k]>a[m]){//一旦找到比a[i]小的数组,立即标注下标;后来依次找到最小值
          k=m;
      }
   }
   if (k!=i){//显然,当k不等于i即a[i]不是最小值时,将找到的最小值下标与i相交换
      t=a[k];
      a[k]=a[i];
      a[i]=t;
   }
}
for (int x:a){//遍历数组foreach操作,实现有序数组的依次输出
   System.out.printf("%d",x);
}

注意,因定义的数组第一个下标为a[0] ,则外层循环次数为a.length-1!故遍历数组时的for循环内为(int i=0;i<a.length/i<=a.length-1;i++)

2.冒泡排序——

基本思想:从数组的第1个元素开始,数组前后两个元素两两比较,如果两个元素的顺序不满足要求,则互相交换位置。这样经过第1轮的比较,数组中的最大的元素到达数组末尾,而经过第2轮的比较,数组中次大的元素到达了数组的倒数第二的...依次循环,当循环到n-1轮时,最后两位最小的数已经顺利排在开头.(PS:由于该排序类似于气泡小的上升、大的沉底,故命名冒泡法;即通常状况下冒泡排序是默认从小到大的)

经典原始代码:

int t;
for (int i=1;i<=9;i++){
    for (int m=0;m<a.length-i;m++){
        if (a[m]>a[m+1]){
           t=a[m];
           a[m]=a[m+1];
           a[m+1]=t;
        }
    }
}
for (int x:a){
    System.out.print(x+" ");
}

❷查找

1.顺序查找

即在遍历数组的过程中依次与设定值比较大小,看是否相等(符合要求).

int a[]={...};
int index=-1;
m=k.nextInt();
for (int i=0;i<a.length;i++){
    if (m==a[i]){//查看是否相同
       index=i;
       break;
    }
}
if (index!=-1){
   System.out.printf("%d",index);//找到一个后输出下标
}else{
      System.out.println("没找到");//没有相等的项
 }

优点:数据无需有序,利用最原始最“暴力”的方式直接筛选;

缺点:效率较低,当数据规模体量大时,时间复杂度大.

2.二分(对分)查找

首先,对于二分查找,数组数据必须是有序的!!!

核心思想——(1)将数组中间位置元素与关键字比较,如果两者相等,则查找结束;反之,进行下一步操作;

(2)利用中间位置元素将数组分为前、后两段,如果中间位置元素大于查找数据,则在前半段进行查找,否则在后半段查找,这样查找范围接近缩小一半.

我们假定既存数组是升序的,Ⅰ.输入一个需要查找的数为key,假设原始数组中就有且只有一个等于key的数据.则原始代码应为:

int key=k.nextInt();
        int i=0,j=a.length-1;
        int m;
        while(i<=j){
            m=(i+j)/2;
            if (a[m]==key){
                System.out.printf("已找到");
                System.out.print(m);
                break;
            }
            elseif (a[m]>key){
                j-=1;
            }
            else {
                i+=1;
            }

Ⅱ. 输入一个需要查找的数为key,假设原始数组中就不止有一个等于key的数据,请找出它的最左侧的值的下标.

思考:如上图的程序段中,当我们得到a[m]等于key时,可以知道应当执行的是j往左移,直到m(中值)到达最左侧的key值,最终i和j不断中移,直到i=j([☆☆☆☆☆]对分查找的退出前的一步一定为i=j)时均到达最左侧的key值的下标,最终根据i和j的值或者最终的m输出下标

int key=k.nextInt();
        int i=0,j=a.length-1;
        int m;
        while(i<=j){
            m=(i+j)/2;
            if (a[m]>=key){
                System.out.printf("已找到");
                System.out.print(m);
                break;
            }
            else {
                i+=1;
            }

二.二维数组

Ⅰ.二维数组的声明

格式为—— <数组元素类型> <数组名称> [] [] ;

<数组元素类型> [] [] <数组名称> ;

例:double [][] a; / double a[][];

Ⅱ. 二维数组的建立 要想真正地存储数据,不仅仅通过声明给出数组名称和可存放数据的类型,更要为其分配内存空间,即创建数组.

语法格式为—— <数组名称>=new <数组类型> [数组行数] [数组列数]

例:int a[][];

a=new int[3][4];

与一维数组相同,也可以对 Ⅰ 、Ⅱ 合二为一,其☆☆☆☆)标准格式为——

<数组元素类型> [ ] <数组名>=new <数组元素类型> [数组长度] 即 :

int [][]a=new int [3][4]; double [][]b=new double [5][8] ;

而java语言中不要求二维数组中每行的元素个数相同——

int [][]a;//此时声明与创建不能合二为一,因为行数与列数不统一
a=newint[3][];
a[0]=newint[2];//此行有2个元素
a[1]=newint[3];//此行有3个元素
a[2]=newint[4];//此行有4个元素

具体元素分布,如下图所示:

编辑

注:起始下标依旧为0!!!

Ⅲ.二维数组的初始化

与一维数组相同,系统会为每个数组分配一个初始值;如int类型为0double类型为0.0.

对于数组的初始化,我们可以采取通过加花括号的方式进行初始化.

  1. 相同列数(每行元素中的元素个数相同)的二维数组

int x[][]={{20,30,60},{11,22,33},{19,13,15}}; // 数组行数为2,列数为3
double y[][]={{61,58},{66,59},{78,79}}; // 数组为2行2列

2.不同列数

int z[][]={{11},{16,18},{46,47,89}}; // 数组z第一行有1个元素,第2行有2个元素,第3行有3个元素

Ⅳ.二维数组元素的引用

再此提醒,二维数组与一维数组相似,数组行下标和列下标的起始值都是0!

而在二维数组中,length属性可以清晰地指明行数和列数。

以a[]数组为例——

  • 行数——<数组名称>.length 例:a.length

  • 列数——<数组名称>[i].length(第i行的元素数) 例:a[i].length

例一: 矩阵的乘法算法.

Am*p的矩阵,B为p*n的矩阵,那么称m*n的矩阵C为矩阵A与B的乘积。其中,矩阵C中的第i行第j列的元素可表示为

编辑

通过鄙人的列举发现规律:

编辑

设二维数组为result[i][j] ,先通过Math.random()进行随机数填充,再通过(☆☆)二维数组的运算执行——

i循环里嵌套j,而j循环里每一趟又会有0~2的增量,故再在j循环里设一个变量k

编辑[0,2],最终可以得到以下代码:

import java.util.*;
publicclasserwei {
    publicstaticvoidmain(String args[]){
        Scanner kc=newScanner(System.in);
        int [][]a={{1,2,3},{4,5,6}};
        int [][]b={{1,4},{2,5},{3,6}};
        int [][]result=newint[a.length][b[0].length];
        for (int i=0;i<a.length;i++){
            for (int j=0;j<b[0].length;j++){
                int k=0;
                while(k<b.length){
                    result[i][j]+=a[i][k]*b[k][j];
                    k++;
                }
                System.out.printf("%d ",result[i][j]);
            }
        }
    }
}


类与对象

一.非静态对象

1.类与对象的定义

首先,Java是一种面向对象的程序设计,用对象可以抽象地来描述现实世界里的具体事物;其次,对象也有一定的属性特征,比如一支笔具有大小、颜色、笔墨粗细等等属性,一个人也同样具有姓名、性别、身高、体重等等属性.我们通常把对象的属性称为对象的数据.

对象又是被包含在类里面的,更形象的讲,是一个总括的共同体,而对象就是隶属于该共同体的的个体

例如,专辑就是一个泛称,而不同的专辑就是一个个独有属性,也就是对象不同的专辑,也拥有不同的姓名、歌手名和出版日期,这些属性/特征被统称为“成员变量”,以及调用这些属性(成员变量)的方法称为“成员方法”,而“赋予”每张专辑的各个属性/特征的方法我们称之为“构造方法”(赋初值)!

(☆☆☆)如,现在定义一个Album类,包含专辑的名称(name)、歌手名(singer)、销售量(sales)和出版年份(years),以及依次显示出各类信息的方法(work),并且定义一个构造方法;同时在main()方法中定义三个不同信息的专辑,并调用work方法进行某一张专辑信息的输出.

class Album {
    //成员变量
    String name;
    String singer;
    double sales;
    int years;
    //构造方法
    Album(String a,String b,double c,int d){
        name=a;
        singer=b;
        sales=c;
        years=d;
    }
    //成员方法
    void work(){
        System.out.println("专辑的名称为"+name+" 歌手/乐队为"+singer+" 总销售量为"+sales+"以及发行年份为"+years);
    }
    public static void main(String args[]){
        //对象的创建
        Album album1=new Album("《The Beatles》(White Album)","The Beatles",30000000,1968);
        Album album2=new Album("《Thriller》","Micheal Jackson",66000000,1982);
        Album album3=new Album("《寓言》","王菲",1000000,2000);
        //成员方法的调用
        album2.work();
    }
}

表1-1

2.对象的创建

对象变量的创建——类名 对象变量名=new 类名(...); (如:Album album2=new Album("《Thriller》","Micheal Jackson",66000000,1982);表示创建一个新的对象Album2

访问成员变量——对象名.成员变量名; (如:Album1.years表示对象Album1的发行年份

调用成员方法——对象名.成员方法名(...);(如:Album3.work();表示对象Album3调用work()成员方法

3.构造方法(☆☆)

⑴构造方法的名字与包含它的类名相同;

⑵构造方法没有返回值,也不能使用void修饰符;

⑶构造方法一般在用new来调用,即对象变量创造时“new 类名(...)”中括号的参数与构造方法中的参数相对应.

例:在类Album中,可创建的构造方法为:

public Album (...){

......

}

如上所示,构造方法名与类名相同,且Album前面没有任何数据类型的前缀.

Ⅰ.无参构造方法

如果我们不使用任何构造方法的话,虽然系统内部会给我们构造一个默认的构造方法,但是各个成员变量不存在初值,我们就需要用访问成员变量的方式自行赋值.如:

(删去Album(String a,String b,double c,int d)...)
Album album1=new Album();
album1.name="《The Beatles》(White Album)";
album1.singer="The Beatles";
album1.sales=30000000;
...

表1-2

我们也可以通过无参构造方法进行部分变量的初始化操作,如在面临毕业生招聘时,大多数应届毕业生的工资与工龄基本相同,此时我们通过无参构造方法对工资和工龄进行初始化,而其余条件进行实例化便能高效实现编程效果:

class Worker{
  String ID;
  int salary;
  int years;
  int age;
  Worker(){
    int salary=4000;
    int years=0;
  }
  Worker worker1=new Worker();
  worker1.ID="Jack";
  worker1.age=25;
  Worker worker2=new Worker();
  worker2.ID="Jackson";
  worker2.age=24;
}

表1-3

上述代码定义了两个工资与工龄相同的不同毕业大学生的信息;顾名思义,无参构造法适用于有部分属性重合的对象的构造, 再对不同属性进行实例化操作即可。

Ⅱ.有参构造方法

如上表1-1所示,

...
public Album(String a,String b,double c,int d){
        name=a;
        singer=b;
        sales=c;
        years=d;
}
...
Album album1=new Album("《The Beatles》(White Album)","The Beatles",30000000,1968);

这就是一种典型的有参构造方法,在构造方法中含有若干种参数并在创建对象时依照参数的顺序进行赋值,此时album1的各个属性(变量)均已齐全!!

(但是必须注意,当已经完成了一种有参方法的构造时,此时系统就不会存在默认的无参构造方法,即此时再输入“Album album4=new Album();”的话系统便会报错!)

(☆☆)this关键字——

若我们在上述参数表内的局部变量(如上表所示为a,b,c,d)与成员变量重名,即构造方法为“public Album(String name,String singer,double sales,int years)”时,我们会发现方法内部参数会被当做局部变量,进而无法进行赋值。为解决此问题,我们可用this关键字进行赋值.

public Album(String name,String singer,double sales,int years){
    this.name=name;
    this.singer=singer;
    this.sales=sales;
    this.years=years;
}

4.方法的重载

对于同一个的成员方法,实际上可以通过增加参数或者改变参数表的内容(个数、类型和顺序)使得多个同名的方法共存,即方法(成员方法和构造方法均可)的重载.如:

class Album {
    String name;
    String singer;
    double sales;
    int years;
    Album(String a){
        name=a;
    }
    Album(String a,String b){
        name=a;
        singer=b;
    }
    Album(String a,String b,double c){
        name=a;
        singer=b;
        sales=c;
    }
    Album(String a,String b,double c,int d){
        name=a;
        singer=b;
        sales=c;
        years=d;
    }
    void work(){
        System.out.println("专辑的名称为"+name+" 歌手/乐队为"+singer+" 总销售量为"+sales+"以及发行年份为"+years);

5.this()的用法

this关键字可以通过“this.变量”进行变量的命名,此外,this关键字还可以进行构造方法的调用。前提是一个类中的构造方法有重载时,可以使用“this(<参数列表>)”使得在一个构造方法内部调用另外一个构造方法.

例:

...
Album(String a,String b,double c,int d){
   name=a;
   singer=b;
   sales=c;
   years=d;
}
Album(String a,String b,double c){
   name=a;
   singer=b;
   sales=c;
}
Album(){
   this("《不知名专辑》","匿名乐队",500,3000);
}

显然,在上述的代码中可以在第13行的“Album()”内部调用第2行的构造方法(因为参数表的参数数目符合),并进行赋值.

进阶复杂版——

public class Waiter{
  int var;
  Waiter(double var){
    this.var=(int)var; 
  }
  Waiter(int var){
    this("Welcome");
  }
  Waiter(String s){
    this();
    System.out.println(s);
  }
  Waiter(){
    System.out.println("Good-bye");
  }
  public static void main(String args[]){
     Waiter t=new Waiter(1);
  }
  //请写出运行结果.

题目解析——

在main()方法中,我们新定义了Waiter类中的对象t,在括号内输入了整数“1”,那么它所指向的构造方法应该是第6行的方法,而此构造方法使用了"this(<...>)"形式,我们需要判断this内部的参数表推算出调用的新的构造方法;显然,“welcome”是一个String类型的,是调用的第9行的构造方法,然而在此构造方法内,又含有了一个新的this(...),同理,因括号内的内容为空,则调用13行的构造方法,我们可以得到输出语句“Goodbye”,现在我们再度回到第九行的构造方法内,第二个语句是输出字符串s的值,即输出字符串“Welcome”.

故最终的结果为“Good-bye(手动换行)welcome”.

二.静态(static)对象成员

对于静态与非静态最大的区别,莫过于静态对象可直接通过类名来调用,而不必创建对象来调用!

例——

class Album {
    String name;
    String singer;
    double sales;
    int years;
    Album(String a,String b,double c,int d){
        name=a;
        singer=b;
        sales=c;
        years=d;
    }
    void work(){//非静态方法
        System.out.println("专辑的名称为"+name+" 歌手/乐队为"+singer+" 总销售量为"+sales+"以及发行年份为"+years);
    }
    static void working(){//静态方法
        System.out.println("祝专辑大卖");
    }
    public static void main(String args[]){
        Album album1=new Album("《The Beatles》(White Album)","The Beatles",30000000,1968);
        album1.work();//非静态方法使用对象进行调用
        Album.woring();//静态方法可直接使用类进行调用
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值