今日主要内容:循环、方法、数组、面向对象基本概念,类,封装
循环
在JAVA中,循环的语法与c语言中几乎完全相同,包括循环体内的变量的生命周期、循环的嵌套等,学过c语言可以直接运用到JAVA中。
在JAVA中运用循环找“水仙花数”的练习中学会的一点小知识:window下的回车是‘\r\n’,其中'\r'是将光标移至行首,'\n'则是换行;而在linux下回车是'\n',mac下回车是'\r'
“水仙花数”练习代码
class Demo_circle{
public static void main(String[] args) {
for (int i=1;i<=10 ;i++ ); //变量的生命周期在一个括号内,这里隐藏了大括号,其实为{;}
{
System.out.println(i); //报错,i在for中声明,多了逗号,for执行完便释放掉了
}
//输出“水仙花数”
int i,j;
for (i=1;i<=9 ;i++ ){
for (j=1;j<=i ;j++ ){
System.out.print(i+"X"+j+"="+(i*j)+" ");
/*if (i==j){
System.out.println("\n");
}*/
}
System.out.println();
}
}
当然,JAVA在循环方面比C语言有一个更贴心的小技巧,就是对循环语句的标号,当然,这个标号其实可以对JAVA中的任一语句,知识在循环中的作用可能更大。特别是又在break中,break后跟语句标签,可以跳出指定的循环,而不仅是当前循环。
//标号与break
a:for (int i = 1; i<=3 ;i++ ){
System.out.println(i);
b:for (int j=1;j<=3 ;j++ ){
System.out.println(j);
break a; //与C语言不通的可以对循环或语句标号,break退出指定标号的循环
方法
JAVA中的方法其实就是对应的C语言中的函数,只是由于JAVA是面向对象的语言,在类的概念下,采用方法的称呼可能更利于理解。
在这方面JAVA比C语言改进的在于方法的重载。重载指相同的方法名,不同的参数列表,与返回类型无关。对于不同的方法允许使用相同的方法名,重载机制通过调用的参数与方法的参数列表进行匹配判断调用的是哪个方法。
重载类型可分为
- 形式参数个数不同
- 形式参数类型不同
- 形式参数顺序不同
//重载:方法名相同,参数列表不同,与返回值无关
/*重载类型:参数个数不同
参数类型不同
顺序不同
*/
class Demo_Overload { //overload重载
public static void main(String[] args) {
int sum1 = add(10,20);
System.out.println(sum1);
int sum2 = add (10,20,30);
System.out.println(sum2);
double sum3 = add (12.3 , 23.4);
System.out.println(sum3);
}
public static int add (int a ,int b ){
return a + b;
}
public static int add (int a ,int b , int c){
return a + b + c;
}
public static double add (double a , double b){
return a + b;
}
}
数组
一维数组方面JAVA和C语言大致相同,不同点如下。
- 声明方式
int[] arr = new int[5]; //动态初始化
//int[] arr1 = new int[]{1,2,3,4,5}; //不允许动静结合
int[] arr2 = {1,2,3,4,5}; //静态初始化
-
JAVA对于数组会有默认的初始化值,C语言则没有。C语言在定义了一个数组后,数组元素的初始化数值与该内存之前存储的数据有关,是随机的值。JAVA对个类型的默认初始化值如下
- 整数类型:byte,short,int,long默认初始化值都为0
- 浮点类型:double,float默认初始化值为0.0
布尔类型:boolean默认初始化值为false
-
字符类型:char默认初始化值为"\u0000"
int[] arr = new int[5]; //动态初始化 System.out.println(arr[0]); //0,JAVA会为各类型数组自动初始化指定的数值 System.out.println(arr); //[I@1db9742
对于数组名的值[I@1db9742 [表示数组,几个表示几维,如[[表示二维;I表示数组类型,I表示的是int型数组,@是固定符号,后面的数字表示16进制的地址名。
- 在我的理解,JAVA中数组是把C语言中声明一个数组,再把数组的地址赋给一个指针连个步骤融合在了一起,JAVA中的数组名相当于指针变量,可以指向不同的数组,而C语言中的数组名是个常量,在声明后是不能改变的。
从JAVA在内存中对数组的分配图表示可以印证我的理解。
关于内存的相关知识
- 栈:存储局部变量
×局部变量:定义在方法声明上的方法中的变量 - 堆:存储new出来的数组或对象
- 方法区:存储类
- 寄存器:给CPU使用
图中在堆中声明了一个数组,把数组的地址传给变量arr,故可以说arr其实就是C语言中的指针变量,甚至可以说JAVA中的引用数据类型就是c中的指针类型。只是JAVA弱化了指针,减少错误使用指针的情况。
二维指针更是充分说明了这一点。在C语言中二维数组仍然是一片连续的存储空间,而在JAVA中二维数组是有几个一维数组通过“指针”练习在一起的。只有一维数组是连续的存储空间。如int[][]arr = new int[2][3],arr[0]和arr的地址是不同,说明了arr[0][0]与arr的地址不是同一个。
通过代码的结果进行验证:
class Demo2_Array1 {
public static void main(String[] args) {
int[][] arr = new int[3][2];
System.out.println(arr); //[[I@1db9742
System.out.println(arr[0]); //[I@106d69c
System.out.println(arr[0][0]); //0
int [][]arr2 = new int[3][];
System.out.println(arr2[0]); //null
System.out.println(arr2[1]); //null
System.out.println(arr2[2]); //null
arr2[0] = new int[2];
arr2[1] = new int[3];
System.out.println("-------------");
System.out.println(arr2[0]); //[I@52e922
System.out.println(arr2[1]); //[I@25154f
System.out.println(arr2[2]); //null
}
}
面向对象
- 面向过程编程的基本单位是函数,函数可以看做是一个动作,或者说行为,如吃(猫,鱼),通过替换参数(主语)可以表示一系列的事物的“吃”的行为。
- 面向对象是为了更好的从现实生活中的逻辑解决问题。将方法封装在对象中。即以名词为主体,将行为封装在其中,如
class 猫{
品种;
毛色;
抓老鼠(){
;
}
}
这样在进行编程的时候可以只需考虑对对象进行操作,问题变成的找对象,操作对象,提高的代码的复用性。当然对于编写对象的程序员来说,这是加大了难度,却造福了众多复用代码的程序员。
类
JAVA的类,是具有相同或相似属性或行为的对象的抽象或者说集合。
从与C语言的关联方面,类可以说是结构体的升级版,即在结构体中融入了函数(方法),使得结构体能对自身进行一系列的“动作”。对象实际是指针变量,声明结构体产生的具体实例,再将其地址赋给对象,对象就可以通过改地址对实例进行访问和修改,仿佛是在操作产生的实例,实则是通过对象这一指针变量间接访问。
类包含成员变量,成员方法,方法。具体定义不详细描述。
class Demo_Person {
public static void main(String[] args) {
Person p = new Person(); //new==malloc? 引用数据类型==指针?
p.speak();
}
}
//关于成员变量的生命周期,其实可用通过c语言中的原理进行解释
//即一个变量的生命周期在其所在的{}代码块的生命周期相同
class Person{
String name; //成员变量,随着对象的存在而存在
int x ;
public void speak(){
int x; //局部变量,随方法调用(入栈)而存在,方法结束(出栈)而消失
x = 10; //局部变量没有初始化值,使用前必须初始化
System.out.println(x); //10,局部变量和成员变量重名采用就近原则
}
}
- 有关于JAVA的垃圾回收机制
当在堆中new出来的对象没有引用数据与其相连,JAVA垃圾回收机制会不定时的将该内存释放掉,即使失去该内存的地址,也不用担心它会一直占用内存而无法释放,这是得JAVA中匿名对象得以使用。
封装
在定义了类之后,一个问题是,大家都可以访问和修改对象的成员变量,而有时非法的修改会造成安全问题。因此,诞生了封装这一概念,对成员变量定义为private,即使其为私有变量,限制访问和修改。
但又不能完全限制,于是通过定义setxxx和getxxx方法对访问和修改的行为进行判断和筛选,当其符合条件是,便允许访问和修改。
import java.util.Scanner;
class Demo_Person {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Person p = new Person();
p.name = "张三";
p.getAge(sc.nextInt());
//System.out.println(p.age); //访问失效,private只能通过给定的方法修改或返回
p.speak();
}
}
class Person{
String name;
private int age;
public void getAge(int age){
if (age > 0 & age < 100){
this.age = age;
}else{
System.out.println("请输入正确的年龄");
}
}
public int setAge(){
return this.age;
}
public void speak(){
System.out.println(name+"..."+age);
}
}
今日最大总结就是:
JAVA的前身是C++,为了使得开发更容易,代码复用性更高,以及简化开发的逻辑而提出的面向对象的概念。通过比较JAVA与C语言的区别与联系,特别是从内存的角度对数组和类的分析,使得对于JAVA中新的知识,如引入型数据,类等抽象的概念在C中找到的对应,对新概念更好的理解。
- 方法 = 函数
- 引用型数据类型 = 指针
- new = 声明或malloc
- class = struct + 函数
由于JAVA有垃圾回收机制使匿名对象有不少的用处,而再C中会造成内存泄漏