Java优点
- 高效
- 健壮
- 跨平台
- 多线程
- 面向对象
Java SE 标准的桌面应用,Java EE Java企业级,Java ME嵌入式的适合硬件
前身:J2SE,J2EE,J2ME
JDK JRE JVM
Java Development Kit Java开发工具包
Java Runtime Environment Java运行环境
Java Virtual Machine Java虚拟机
JDK包含JRE,JRE包含JVM
类和对象
对象:万物皆对象。一切在现实生活中存在的事物都是对象,它有自己的属性和方法。
类:所有一类对象的集合,它们有共同的特性和行为。类是对象抽象,是一个概念,是一个模板。
类是对象的模板,对象是类的实例。
OOP:Object-oriented Programming面向对象编程
封装
1.封装可以隐藏数据,不让外界直接访问,对外提供接口来间接访问被隐藏的数据。
比如对象中的一些属性设置为私有的,只有对象内部访问,不对外开放,避免重要数据被修改。
2.封装可以包装实现细节,对外提供一个方便的接口访问,使程序简洁。
一些方法可能比较复杂,但是对外提供一个简单的接口就可以访问,而不用关注实现的细节,同时这个方法可以重复调用,使的代码简洁高效。
注释
三种注释:
1.单行注释//
适合注释内容少,简洁明了的内容
2.多行注释
适合内容较多的说明性的注释,比如某段代码的设计思想和实现步骤
3.文档注释
对类成员的注释描述,将来生成javadoc(java帮助文档)时使用, 这些注释会出现在文档中。
抽象
抽象是把现实世界中的事物映射到程序中类的过程。抽象是一个过程,是一个技术,是面向对象设计的基础。
比如开发一个图书管理系统,就要对现实世界中的图书信息进行分析,并在程序中用Book类来表示,这个Book类对应现实中的书的信息,因为书有书名、售价、作者、出版社等信息,在Book类中也应有这些信息,它们叫做属性:
public class Book{
/**
* 编号
*/
int id;
/**
* 书名
*/
String name;
/**
* 售价
*/
float price;
/**
* 作者
*/
String auth;
}
完成现实到程序中的转换工作就是抽象的工作。
访问权限
前面提到了封装,为了有效保护对象的属性,不能直接访问,所以就要有一个机制来支持封装,它就是私有化private,把对象的属性定义成私有化,这些属性就只能在类内部访问,在类外部是无法访问的,把上面的Book类改为下面的:
public class A {
/**
* 编号
*/
private int id;
/**
* 书名
*/
private String name;
/**
* 售价
*/
private float price;
/**
* 作者
*/
private String auth;
}
如果上述属性被设置为私有后,外界就无法访问了,但同时也无法使用这些数据了,为了解决这个问题,就需要为每个属性提供一个对外服务的接口(方法),这些方法是公开的,这样就可以访问了,虽然看似多余的有一个方法层,但这样可以在外界访问这些方法时,Book能做一些相应的处理。
/**
* 给name属性赋值
*/
public void setName(String name){
在此判断参数name是否为空,如果为空则抛出一个异常,阻止改变name为空的操作
如果参数name不是空的则属性name=参数name
}
方法
方法的声明(签名)由以下几部分组成:
访问修饰符+返回值+方法名(参数列表)
上面因为属性是私有的,要想让别的类来访问这些属性就要提供一个方法,这个方法的访问修饰符至少不能是私有的。
对于这些属性对应的方法,一般都是getXX setXX,俗称get/set方法,get返回属性,set返回void,void就是没有返回值的意思。
/**
* 获取值
*/
public int getId(){
return id;
}
/**
* 设置值
*/
public void setId(int idPara){
id = idPara;
}
有一种方法比较特殊,就是构造方法,它的特点是没有返回值,方法名必须和类名一致:
public class Student{
/**
* 构造方法
*/
public Student(){}
}
一般没有必要定义构造方法,如果一个类中没有定义构造方法,则JVM会自动给当前类创建一个构造方法,这个方法只在JVM中存在。但是如果你的类中有自己写的构造方法,JVM就不再生成新的构造方法。
构造方法专门用来创建对象实例的,可以在构造方法中对属性的值进行初始化。
有一种构造方法叫默认构造方法:
public 类名(){
方法体
}
这个构造方法是public,并且没有参数列表的,即为默认构造方法
构造方法主要是初始化对象的,可以在构造方法的参数列表中设置属性信息,完成对象的初始化
public class Student{
private int id;
private String name;
// 默认构造方法(无参)
public Student(){
id = 0;
name=null;
}
// 自定义构造方法
public Student(int idPara,String namePara){
id = idPara;
name = namePara;
}
}
实例和调用
用new来创建类的一个实例
Student student = new Student();
类名 对象名 = new 类名();
调用对象中的属性和方法(对象的成员)用点操作符:
int id = student.getId();
student.setName('Tom');
this
Student student = new Student();
JVM在堆中开辟一块空间给student对象,又让student变量指向了这块地址,我们通过student变量操作对象。但是在Student对象内部它是如何操作这块地址内,答案是通过this关键字,this又是怎么来的?
Student student = new Student(this); 其实在new操作时,构造方法向对象中传入一个内部引用this指针,没错,this是内部的指针,student是外部指针,它们指向的是同一块地址。这样就可以解决内部调用的问题。
public class Student{
int id;
public int getId(){
return this.id;
}
public void setId(int id){
this.id = id;
}
}
main{
Student student = new Student();
student.id = 1; 在外部访问id
student.setId(1);在内部访问id this.id=id
}
public Student(int id,String name){
this.id = id;
this.name = name;
}
this.id指向的是对象中的属性id,参数中的id只是一个临时变量,如果写成 id=id前面的id意欲属性id,后面的id是参数id,但是这样程序无法区分哪个id是哪个id,所以此处用this.id标记属性的id,参数id还是id。
toString
toString方法是输出对象的信息,把对象以字符形式描述出来,如果不写toString方法时,sout(student)将输出student的内存地址,而无法输出student对象真实信息,我们一般调用toString方法时,都会对此方法进行改造。
public String toString(){
return “id:” + this.id + “,name:” + this.name;
}
这儿的this指针会指向对象的内存地址,并且取出相应的属性。
类代码中的结构约定:1.写私有属性;2.写非私有属性;3.写构造方法;4.写get/set方法;5.写toString方法
数据类型
在展开Java开发之前,有必要对Java的数据类型说明一下:
Java中有两大数据类型:1.原始数据类型;2.引用数据类型
原始数据类型的变量值是保存在栈中,引用数据类型是保存在堆中。
数据类型用适合的类型可以省内存,提高程序性能。
原始数据类型有八个:
类型 | 有效数据 | 占用内存 | 取值范围 | 默认值 |
---|---|---|---|---|
boolean | 布尔 | - | true/false | false |
byte | 整数 | 1个字节 | -27~27-1 -128~127 | 0 |
short | 整数 | 2个字节 | -215~215-1 -32768~32767 | 0 |
char | 字符 | 2个字节 | 0~215-1 | \u0000 |
int | 整数 | 4个字节 | -231~231-1 -2,147,483,648~2,147,483,647 | 0 |
long | 整数 | 8个字节 | -263~263-1 | 0 |
float | 浮点 | 4个字节 | 0.0 | |
double | 浮点 | 8个字节 | 0.0 |
在上述类型中,boolean类型官方没有明确给定内存占用情况,不过它的取值只能是true或false。
几个整形的数据的取值是它们占用内存的字节数*8位,因为要拿出一位来存放数据的符号正或负,我们称之为符号位,这样字节数 * 8还要减1才是有效存储数据的位数。
除原始类型外,就是复杂的数据类型,它们就是引用数据类型,这些类型的数据在内存中没有固定大小,没有取值范围,它们在内存中的大小取决于它们类的设计,和它们对象属性的值。
注意:给long型变量赋值时,如果值大于int型的最大范围,则要在数字后加L或l,正因为小写的l和1容易混淆,所以建议加L;给float型变量赋值时要在值的后面加f或F,因为不加时默认是double型,无法给float型赋值。
几个基本数据类型的可以互相转换:
byte->short->int->long
byte->char->int->long
boolean flag = true;
byte b = 1;
short s = 1;
// 小类型向大类型可以自动转换
s = b;
// 大类型向小类型转换需要强制转换
b = (byte)s;
// Required type:byte Provided:int,超出了范围
// 因为128是常量,编译器会立即发现这个错误
//b = 128;
s = 128;
// 因为s是变量,骗过了编译器
b = (byte)s;
// 输出-128,因为b溢出了
System.out.println("b=" + b);
// 有格式的输出
System.out.printf("b=%d",b);
byte b = 1;
// 运算后自动提升为高类型数据1为int,结果为int型
// b = b + 1;
b = (byte)(b + 1);
// 类中生成的代码同上,此处是语法糖
b+=1;
byte b = 97;
// 虽然b是小类型c是大类型,但因为b和c不是同一类型,需要强转
char c = (char)b;
// c=a
System.out.println("c=" + c);
b = (byte)c;
// b=97
System.out.println("b=" + b);
long num1 = 99999999999L;
// 虽然long型是8个字节,float是4个字节,但是整数可以自动转成
// 但是精度会丢失
float f = num1;
System.out.println("f=" + f);
long num2 = (long)f;
// 转了一圈发现相差了-2047
System.out.printf("%d-%d=%d",num2,num1,(num2-num1));
// 格式化输出浮点数时,用%f
System.out.printf("%f",1.23);
float f = 1.1f-0.8f;
// f=0.3
System.out.println("f=" + f);
// true
System.out.println("f==0.3f:" + (f == 0.3f));
// false
System.out.println("f==0.3:" + (f == 0.3));
double d = 1.1f - 0.8f;
// d=0.30000001192092896
System.out.println("d=" + d);
d = 1.1 - 0.8;
// d=0.30000000000000004
System.out.println("d=" + d);
Scanner
可以从键盘或文件或网络中获取数据,一般从键盘获取数据比较多
next()从输入缓冲区中获取一个数据
nextLine()从输入缓冲区中获取一行数据
nextInt()获取一个数字
构造方法有一个参数System.in 系统输入
命名
1.只能是字母、数字、下划线、$
2.不能是数字开头
3.不能用Java关键字、保留字、字面值
保留字:goto、const,字面值:true/false/null
4.驼峰,见名知意,
5.常量的命名:全大写,在单词和单词之间用下划线隔开
DB_SUCCESS SYS_MAX_VALUE 看到大写的就是常量
final int DB_SUCCESS=1; 常量的值是不可以变的,一但赋值后。
String
String是常用类,很有个性类。
String name = “name1”;在字符串常量池中寻找有没有常量"name1",如果没有则开辟空间,存放。
字符串常量池,“name1"就会放到常量池中,
String name2 = “name1” 就不会在堆中开辟空间,而是复用常量池中的"name1”
String name3 = new String(“xx”);此时创建了两个对象一个是字符串对象,一个是"XX"自身这个对象。
String name1 = "name1";
String name2 = "name1";
// 此处是比较两个变量name1和name2的值
System.out.println(name1 == name2);
String name3 = new String("name1");
// false new的时候必定在堆中开辟一个空间也就有了新的地址
// name3的地址不再是name1常量的地址
System.out.println(name1 == name3);
System.out.println("name1=" + name1);
System.out.printf("name3=%s",name3);
System.out.println();
// new 相当于开房,s1相当于开完房给的钥匙
// 此行代码在内存中创建了两个对象
String s1 = new String("s1");
String s2 = new String("s1");
System.out.println(s1 == s2);
System.out.println("s1=" + s1);
System.out.println("s2=" + s2);
数组
一组相同类型的数据的集合。
数组是有长度的,可以通过数组对象的下标去访问数组中的每一个元素,可以通过属性length获取数组的长度,数组元素的个数。
数据类型[] 数组变量名 = 初始化数组
// 数组是有固定长度,数组的元素类型是一样的
// 只知道数组的长度和类型
// 数组在创建后,它的元素是该数据类型的默认值
// 0,0,0
byte[] bs = new byte[3];
// 没有指定数组长度,但是用数据来初始化数组
// 利用一组数据来创建数组,同时指定了数组的每一个元素
byte[] bs2 = new byte[]{1,2,3};
byte[] bs3 = {1,2,3};
// 数组对外提供自己的内存地址给数组变量
// 数组在内存中有一个统一的对外访问的地址,数组中的每一个元素
// 是通过这个地址加下标来访问
System.out.println(bs3);
// 第一个元素,下标是0
System.out.println(bs3[0]);
bs3[1] = 11;
System.out.println(bs3[1]);
// 不建议用这种方式定义
byte bs4[] = new byte[3];
二维数组
// 二维数组
byte[][] arr = new byte[3][];
// 第一维有三个元素,而第一维中的每一个元素又是一个数组
arr[0] = new byte[3];
arr[1] = new byte[4];
arr[0][0] = 1;
arr[0][1] = 2;
arr[0][2] = 3;
arr[2] = new byte[]{3,2,1};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
// 二维数组的最后一个元素
System.out.println(arr[2][2]);
byte[] b = {1, 2, 3};
// 工具类Arrays
System.out.println(Arrays.toString(b));
流程
if else if
switch case
int age = 18;
if (age >= 18) {
System.out.println("成年人");
}else{
System.out.println("未成年");
}
System.out.println("-------------图书管理系统-------------");
System.out.println("1.增加图书");
System.out.println("2.修改图书");
System.out.println("3.删除图书");
System.out.println("请选择菜单项:");
Scanner scanner = new Scanner(System.in);
int select = scanner.nextInt();
// switch后面的表达式可以是哪些数据类型:
// byte short int char String enum
switch (select){
case 1:
System.out.println("增加图书");
// 对每一个case都要加break中断,否则会从此case进入下一个case
break;
case 2:
System.out.println("修改图书");
break;
case 3:
System.out.println("删除图书");
break;
default:
System.out.println("选项错误");
}
// 释放内存及系统资源
scanner.close();
public enum Week {
// 不用写类型,直接写常量名
// 相当于Week类可以枚举出的范围
MON,TUE,WED,THI,FRI,SAT,SUN
}
main:
Week week = Week.FRI;
switch(week){
case MON:
System.out.println("周一");
break;
case FRI:
System.out.println("周五");
break;
default:
System.out.println("other");
}
for
continue,break
continue是结束当次循环,进入下一次循环
break是中断当前循环
while doWhile
常用类(包装数据类型,高精度数字类)
金刚般若波罗蜜经
智慧到彼岸
烦恼是此岸,普提就是彼岸
轮回是此岸,解脱就是彼岸
生死是此岸,涅槃就是彼岸