第一、二章 对象
对象、类、方法:
对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
类:类是一个模板,它描述一类对象的行为和状态。
方法:方法就是行为,一个类可以有很多方法。逻辑运算、数据修改以及所有动作都是在方法中完成的。
实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定
Java中类的定义:
public class Dog{
String breed;
int age;
String color;
void barking(){
}
void hungry(){
}
void sleeping(){
}
}
创建对象
对象是根据类创建的。在Java中,使用关键字new来创建一个新的对象。创建对象需要以下三步:
- 声明:声明一个对象,包括对象名称和对象类型。
- 实例化:使用关键字new来创建一个对象。
- 初始化:使用new创建对象时,会调用构造方法初始化对象。
public class Puppy{
public Puppy(String name){
//这个构造器仅有一个参数:name
System.out.println("小狗的名字是 : " + name );
}
public static void main(String[] args){
// 下面的语句将创建一个Puppy对象
Puppy myPuppy = new Puppy( "tommy" );
}
}
成员变量和类变量的区别
- 由static修饰的变量称为静态变量,其实质上就是一个全局变量。如果某个内容是被所有对象所共享,那么该内容就应该用静态修饰;没有被静态修饰的内容,其实是属于对象的特殊描述。不同的对象的实例变量将被分配不同的内存空间, 如果类中的成员变量有类变量,那么所有对象的这个类变量都分配给相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量。
- 成员变量和类变量的区别:
- 两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的回收而释放。 静态变量随着类的加载而存在,随着类的消失而消失。 - 调用方式不同 成员变量只能被对象调用。 静态变量可以被对象调用,还可以被类名调用。
- 别名不同 成员变量也称为实例变量。 静态变量也称为类变量。
- 数据存储位置不同 成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
static 关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
- 特点:
- 想要实现对象中的共性数据的对象共享。可以将这个数据进行静态修饰。
- 被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
- 静态随着类的加载而加载。而且优先于对象存在。
- 弊端:
- 有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
- 静态方法只能访问静态成员,不可以访问非静态成员。 因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
- 静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用
变量和数据类型
- 变量:是存储数据的基本单元,相互独立
- 数据类型:
- int(整型)
- double(双精度浮点型)
- char(字符型)
- String(字符串)
- boolean布尔类型(判断型)
- 变量必须先声明赋值才能使用 (数据类型 变量名=值)
- 变量命名规则
- 首字母:小(首字母小写)下(可以含有下划线)美(可以含有$符号)
- 其它的字母:小、下、美、数字
- 不能使用java关键字
自动类型转换
- 数据类型要兼容
- 目标类型大于原类型
- 强制类型转换 目标类型小于源类型
第三章 操作符
访问控制修饰符
Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public : 对所有类可见。使用对象:类、接口、变量、方法
- protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
访问控制和继承
- 父类中声明为 public 的方法在子类中也必须为 public。
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
- 父类中声明为 private 的方法,不能够被继承。
Java 运算符
算术运算符
实例
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 25;
int d = 25;
System.out.println("a + b = " + (a + b) );
System.out.println("a - b = " + (a - b) );
System.out.println("a * b = " + (a * b) );
System.out.println("b / a = " + (b / a) );
System.out.println("b % a = " + (b % a) );
System.out.println("c % a = " + (c % a) );
System.out.println("a++ = " + (a++) );
System.out.println("a-- = " + (a--) );
System.out.println("d++ = " + (d++) );
System.out.println("++d = " + (++d) );
}
}
关系运算符
实例
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a == b = " + (a == b) );
System.out.println("a != b = " + (a != b) );
System.out.println("a > b = " + (a > b) );
System.out.println("a < b = " + (a < b) );
System.out.println("b >= a = " + (b >= a) );
System.out.println("b <= a = " + (b <= a) );
}
}
位运算符
实例
public class Test {
public static void main(String[] args) {
int a = 60; /* 60 = 0011 1100 */
int b = 13; /* 13 = 0000 1101 */
int c = 0;
c = a & b; /* 12 = 0000 1100 */
System.out.println("a & b = " + c );
c = a | b; /* 61 = 0011 1101 */
System.out.println("a | b = " + c );
c = a ^ b; /* 49 = 0011 0001 */
System.out.println("a ^ b = " + c );
c = ~a; /*-61 = 1100 0011 */
System.out.println("~a = " + c );
c = a << 2; /* 240 = 1111 0000 */
System.out.println("a << 2 = " + c );
c = a >> 2; /* 15 = 1111 */
System.out.println("a >> 2 = " + c );
c = a >>> 2; /* 15 = 0000 1111 */
System.out.println("a >>> 2 = " + c );
}
}
结果:
a & b = 12
a | b = 61
a ^ b = 49
~a = -61
a << 2 = 240
a >> 2 = 15
a >>> 2 = 15
逻辑运算符
实例:
public class Test {
public static void main(String[] args) {
boolean a = true;
boolean b = false;
System.out.println("a && b = " + (a&&b));
System.out.println("a || b = " + (a||b) );
System.out.println("!(a && b) = " + !(a && b));
}
}
结果:
a && b = false
a || b = true
!(a && b) = true
短路逻辑运算符
当使用与逻辑运算符时,在两个操作数都为true时,结果才为true,但是当得到第一个操作为false时,其结果就必定是false,这时候就不会再判断第二个操作了。
实例:
public class LuoJi{
public static void main(String[] args){
int a = 5;//定义一个变量;
boolean b = (a<4)&&(a++<10);
System.out.println("使用短路逻辑运算符的结果为"+b);
System.out.println("a的结果为"+a);
}
}
结果:
使用短路逻辑运算符的结果为false
a的结果为5
赋值运算符
实例:
public class Test {
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 0;
c = a + b;
System.out.println("c = a + b = " + c );
c += a ;
System.out.println("c += a = " + c );
c -= a ;
System.out.println("c -= a = " + c );
c *= a ;
System.out.println("c *= a = " + c );
a = 10;
c = 15;
c /= a ;
System.out.println("c /= a = " + c );
a = 10;
c = 15;
c %= a ;
System.out.println("c %= a = " + c );
c <<= 2 ;
System.out.println("c <<= 2 = " + c );
c >>= 2 ;
System.out.println("c >>= 2 = " + c );
c >>= 2 ;
System.out.println("c >>= 2 = " + c );
c &= a ;
System.out.println("c &= a = " + c );
c ^= a ;
System.out.println("c ^= a = " + c );
c |= a ;
System.out.println("c |= a = " + c );
}
}
结果:
c = a + b = 30
c += a = 40
c -= a = 30
c *= a = 300
c /= a = 1
c %= a = 5
c <<= 2 = 20
c >>= 2 = 5
c >>= 2 = 1
c &= a = 0
c ^= a = 10
c |= a = 10
条件运算符
条件运算符也被称为三元运算符。该运算符有3个操作数,并且需要判断布尔表达式的值。该运算符的主要是决定哪个值应该赋值给变量。
实例:
public class Test {
public static void main(String[] args){
int a , b;
a = 10;
// 如果 a 等于 1 成立,则设置 b 为 20,否则为 30
b = (a == 1) ? 20 : 30;
System.out.println( "Value of b is : " + b );
// 如果 a 等于 10 成立,则设置 b 为 20,否则为 30
b = (a == 10) ? 20 : 30;
System.out.println( "Value of b is : " + b );
}
}
结果
Value of b is : 30
Value of b is : 20
运算符优先级
equals和==
equals没重写时候和==一样,比较的是对象的地址,题中new 了两个对象,所以各自地址不一样,使用equals比较为false,但是string类型中的equals方法Java默认重写了,可以比较对象里的值;两个对象指向的同一个string成员变量里的值相同,所以eqauals比较也相同。
第四章 控制执行流程
条件语句
if…else语句
if 语句后面可以跟 else 语句,当 if 语句的布尔表达式值为 false 时,else 语句块会被执行
public class Test {
public static void main(String args[]){
int x = 30;
if( x < 20 ){
System.out.print("这是 if 语句");
}else{
System.out.print("这是 else 语句");
}
}
}
if…else if…else 语句
if 语句后面可以跟 else if…else 语句,这种语句可以检测到多种可能的情况。
使用 if,else if,else 语句的时候,需要注意下面几点:
- if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
- if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
- 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
public class Test {
public static void main(String args[]){
int x = 30;
if( x == 10 ){
System.out.print("Value of X is 10");
}else if( x == 20 ){
System.out.print("Value of X is 20");
}else if( x == 30 ){
System.out.print("Value of X is 30");
}else{
System.out.print("这是 else 语句");
}
}
}
嵌套的 if…else 语句
public class Test {
public static void main(String args[]){
int x = 30;
int y = 10;
if( x == 30 ){
if( y == 10 ){
System.out.print("X = 30 and Y = 10");
}
}
}
}
循环结构 - for, while 及 do…while
while 循环
while是最基本的循环,它的结构为:
while( 布尔表达式 ) {
//循环内容
}
只要布尔表达式为 true,循环就会一直执行下去.
do…while 循环
对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do {
//代码语句
}while(布尔表达式);
注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。
如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
for循环
虽然所有循环结构都可以用 while 或者 do…while表示,但 Java 提供了另一种语句 —— for 循环,使一些循环结构变得更加简单。
for循环执行的次数是在执行前就确定的
break关键字
break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
break 跳出最里层的循环,并且继续执行该循环下面的语句。
continue 关键字
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
第五章 初始化与清理
类的构造方法
- 构造方法的名字和类名相同,并且没有返回值。
- 构造方法主要用于为类的对象定义初始化状态。
- 我们不能直接调用构造方法,必须通过new关键字来自动调用,从而创建类的实例。
- Java的类都要求有构造方法,如果没有定义构造方法,Java编译器会为我们提供一个缺省的构造方法,也就是不带参数的构造方法。
this关键字
- 解决成员变量和参数(局部变量)之间的二义性必须使用。
- 同类中实例方法间互相调用(此时可以省略this,但不建议省略)。
- 将this作为参数传递给类中另一个方法。
- 将this作为方法的返回值(链式方法编程)。
- 构造器重载的互调,this([参数])必须写在构造方法第一行。
- static不能和this一起使用
用构造器确保初始化
- 如果没有构造器,那么就会有一个构建方法,这个方法需要我们在使用对象之前去创造对象,使得对象初始化,如何命名这个方法呢?它可能会和成员方法的名字相同了,如何让编译器轻松的找到这个方法。java采用的方法是采用类名作为构造方法的名字。当我们new 一个对象的时候,会为对象分配空间,调用类的构造器,初始化对象数据。默认的构造器就是无参构造器。构造器的使用,有利于我们减少错误,使得代码更容易阅读。构造器是一种特殊的方法,他没有返回值也没有把这个方法定义为
void。 new 表达式确实返回了对新对象的引用, 然而构造器并没有返回任何类型。
默认构造器
- 如果我们没有创建构造器,编译器会为我们构建默认的无参构造器。当然如果我们已经创建了,编译器就不会构建默认构造器。
方法重载
- 为什么要有方法重载? 我们在描述一个方法名的时候,想实现的效果是一样的含义比如print 它表达了同样的行为方式,如果没有重载我们会怎么描述print printInt printString printLong等等,这样很冗余。又例如我们的构造方法,如果没有方法重载,那么我们就不能有不同形式的构造对象的形式。因为方法名要独一无二。有了方法重载有什么好处?他们的名字相同,他们表达相同的行为,不同的是他们的参数列表,这样我们可以把所有类型的输出都叫print
把所有形式的构造方法都定义为类名。 - 对于涉及到基础类型的重载,我们要注意 基本数据类型可以向上转型。
- 我们通过参数列表进行区分不同的方法而不是采用返回值来区分不同方法的原因是当我们需要执行一个方法,只是单纯的调用这个方法,不知道返回值类型的时候我们就不知道调用的是哪个方法了。