Java笔记补充
第一章 入门
-
Java不依赖于平台,是因为java虚拟机的存在。
-
JVM:JVM是(Java Virtual Machine)Java虚拟机的简称,我们如果想和计算机交流,那JVM就是这两者交流中的介质。
-
JDK和JRE的区别:
- JRE(Java Runtime Environment)是Java运行环境的简称。JRE由JVM和Java程序中所需的核心类库组成。JRE=JVM+类库
- JDK(Java Development Kit)Java开发工具包的简称。其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就不用再单独安装JRE。JDK=JRE+Java开发工具。
- 关系:使用JDK开发完成java程序,交给JRE运行
-
Java是纯粹的面向对象的程序设计语言,C++是面向对象和面向过程都支持的程序设计语言,这是因为C语言是C++的子集,而C语言是面向过程的程序设计语言。
-
Java应用程序开发步骤:
(1)编写源文件。文件扩展名必须是.java。
(2)编译源文件。使用javac.exe编译。得到字节码文件。
(3)使用Java SE平台中的Java解释器(java.exe)来解释字节码文件。 -
一个java文件只能有一个public class
-
反编译:把编译器得到的字节码文件还原为源文件。C语言生成的是机器码,所以很难在反编译。java的反编译器是:javap.exe。不能反编译出方法内容,只能反编译出方法名。
-
如果控制台显示“无法加载主类”的问题,应该看看我们的CLASSPATH的配置前面有没有加“.;”,这个点表示当前路径。也可以在控制台设置
set classpath=.
来解决问题。 -
Java中的数组,它的[]可以放在类型后面,也可以放在形参后面。有一点点小区别。
-
在控制台使用
javac Hello.java
来编译源文件,使用java Hello
来执行文件。
(1)javac命令可以将java源文件编译为class字节码文件。
(2)java命令可以运行字节码文件。 -
使用文本编辑器写Java代码时,一定要用ANSI码保存文件。
-
javac是JDK提供的编译器。
-
javac为编译器,javap为反编译,javadoc为生成帮助文档。jjava为解释器。
-
Java命名规则是类的首字母大写。方法和变量首字母小写,例:setName。标识符不能以数字打头,可以用_,不能用-。
-
byte short int long 在赋值数字是不区分精度大小,但使用变量赋值时,是区分精度的。
-
byte的范围是:-128~127
-
Java语言使用Unicode标准字符集,最多可以识别65536个字符
-
低精度的可以隐式的转为高精度。高精度不能隐式的转换,只能强制类型转换。
-
JDK1.5新增了和C语言中printf函数类似的输出数据的方法。
- 格式如下:
System.out.printf(“格式控制部分”,表达式1,表达式2,…表达式n) - 格式控制部分由格式控制符号:%d、%c、%f、%s和普通的字符组成,普通字符原样输出。格式符号用来输出表达式的值。
- %d输出int类型数据值;%c输出char型数据;%f输出浮点型数据,小数部分最多保留6位;%s输出字符串数据。
- 输出数据时也可以控制数据在命令行的位置,例如:%md输出的int型数据占m列;%m.nf输出的浮点型数据占m列,小数点保留n位。
- 格式如下:
-
System.out.printf("%20.8f",x);
。20为域宽,8为保留小数位数。 -
输入基本型数据,可以使用Scanner类创建一个对象。
Scanner reader=new Scanner(System.in);
。- 其中:reader对象调用下列方法,读取用户在命令行输入的各种基本类型数据:nextBoolean()、 nextByte()、 nextShort()、 nextInt() 、 nextLong()、nextFloat()、nextDouble()。
- 上述方法执行时都会堵塞,程序等待用户在命令行输入数据回车确认。
-
数组:
(1)声明一维数组有下列两种格式:- 数组的元素类型 数组名[];
- 数组的元素类型 [] 数组名;
- 例如:
float boy[];
char[] cat;
(2)声明二维数组有下列两种格式:
- 数组的元素类型 数组名[][];
- 数组的元素类型 [][] 数组名;
- 例如:
float a[][];
Char [][] b;
-
为一维数组分配元素的格式如下:
- 数组名 = new 数组元素的类型[数组元素的个数];
- 例如: boy = new float[4];
- 数组的声明和分配空间可以在声明时同时完成:
float boy []=new float[4];
1.1 IDEA真香
- IDEA的一个实用功能:Split Vertically,对照其他代码修改代码很方便
- Run:Alt+Shift+X
- 修改变量或方法名:Alt+Shift +r
- 查找替换:Ctrl+f或Ctrl+h
- 查找方法在哪被调用过:Ctrl +Shift+h
- 快捷操作:
(1)Run:Alt+Shift+X
(2)main方法:psvm(可以在Live Templates修改,main)
(3)输出:sout+回车。或者"Hello".sout。
(4)循环:fori
(5)遍历数组:itar
(6)在文件的settings的Live Templates查看模板。
(7)可以在Live Templates中自定义模板。
第二章 运算符、表达式、语句
- 如果表达式中最高精度是double(float、long)类型,则按double(float、long)运算。
- 如果表达式最高精度低于int型,则按int精度进行运算。
- java允许把不超出byte,short,char的取值范围的算术表达式的值赋值给byte,short,char。例如:(byte)30+'a"是结果为127的int型。a为97。
int m=1;
byte x;
x=1+'a';//x=98.
//x = m+'a';是错的
- 关系运算符只能得到true或false。和C不一样,C得到的是1或0。
- 尽量把常量写左边。j
- java逻辑运算符&&,||,!两边只能是布尔类型表达式(即:只能是true&&false之类的。)。java不能是4&&5之类的,C则可以。
- 位运算:按位与,按位或,按位异或(^)。二进制。
- in
- java的条件表达式只能是布尔类型的。if,while,
- switch语句的括号里面不能是long类型的值。
- for(声明循环变量:数组名){……}。循环变量依次与数组的每一个元素。这个循环变量不能在外面声明。
第三章 类和对象
-
类的组成:
(1)成员变量。和声明位置无关。- 有默认值
- 有效范围是整个类。
- 声明成员变量给初值不是赋值语句。
- 不能在类中定义变量之后再给赋值语句。即:类体中没有语句,只能在方法体内。
(2)方法。方法中有局部变量。
- 局部变量与声明位置有关。
- 局部变量和成员变量同名,则在方法体内,成员变量被隐藏,暂时失效。
- 使用this关键字使用成员变量。
- 局部变量没有默认值,不是C语言中的垃圾值。
-
构造方法:创建对象时使用。
(1)名字和类名完全相同,没有类型。
(2)默认构造方法:我们没有写构造方法,编译器会自动加一个构造方法。
(3)自定义构造方法。我们写了构造方法,编译器不会加默认构造方法。可以有多个构造方法(重载)。 -
创建对象:类是一种数据类型。
(1)声明对象:类声明的变量叫对象变量。相当于给对象起个名。
(2)创建对象:使用new关键字为对象分配变量。即:实例化。相当于把这个对象造出来。
(3)对象声明之后只是个空对象。只有在new之后才是一个完整的对象。我们要避免使用空对象,不然会出现编译通过,但是运行出错。 -
使用对象:
(1)对象.变量。对象.方法。 -
对象的引用和实体:
(1)对象本身中存放着引用,自己可以操作分配给自己的变量,调用类提供的方法。
(2)分配给对象的变量称为对象的“实体”。
(3)两个类型相同的对象,如果二者的引用相同(赋值),那么二者就具有完全相同的“实体”。例:obj1 = obj2
-
类与程序的基本结构:
(1)一个Java程序(工程)由若干个类构成。
(2)这些类可以在一个源文件中,也可以分布在多个源文件中。提倡一源文件一个类。
(3)有main方法的类叫主类。一个源文件只能有一个public类。public类的类名必须和源文件名一样。 -
参数传值:
(1)传值机制:方法中参数变量的值是调用者指定的值的拷贝。
(2)基本数据类型参数的传值。
(3)引用类型参数的传值。- 比如:数组
int [] a;a = new int[4];
,对象都是引用类型。 - 方法的参数是数组或对象时,把实参的值拷贝到形参中,实参和形参就指向同一个东西,即:可以通过形参改变实参的值。
- 比如:数组
-
对象的组合:
(1)一个类可以把某个对象作为自己的一个成员变量。 -
组合与复用:
(1)如果一个对象a组合了对象b,那么对象a就可以委托对象b调用其方法,即对象a以组合的方式复用对象b的方法。
(2)通过组合对象来复用方法有以下特点:- 通过组合对象来复用方法也称为“黑盒”复用,因为当前对象只能委托所包含的对象调用其方法,这样一来,当前对象对所包含的对象的的方法的细节一无所知。即:在类的内部使用这个对象成员的方法。
- 当前对象随时可以更换所包含的对象,即:对象与所包含的对象属于弱耦合的关系。
- 【注意】一个类声明的两个对象如果具有相同的引用,二者就具有完全相同的变量(实体)。
-
实例变量和类变量:在类成员中加static修饰符的是类变量,否则就是类变量(静态变量)。
(1)区别:- 不同对象的实例变量互不相同。
- 所有对象共享类变量。
- 通过类名可以直接访问类变量。不需要通过对象。而实例变量只能通过对象访问。
-
实例方法和类方法的定义:使用static关键字。
(1)实例方法:没有使用static关键字修饰的方法叫实例方法。
(2)类方法:使用static关键字修饰的方法叫类方法。
(3)区别:- 通过对象调用实例方法,只能通过对象。实例方法可以操作所有变量。
- 可以通过类名调用类方法。也可以通过对象。类方法只能操作类变量(静态变量)。
- 如果不需要操作成员变量,就可以将这样的方法写成静态的。比如:库函数Arrays.sort(a);,就是直接使用Arrays这个类名调用sort这个方法。
- 不能在静态方法中直接使用非静态的方法。如下,
void fun1()
{
System.out.println("oio");
}
static void fun()
{
fun1();
System.out.println("he");
}
编译出错。
- 方法重载:Java中有两种多态:重载和重写。
(1)重载:一个类中可以有多个相同名字的方法,但必须保证方法的参数不同。不能以方法返回值区分。 - this关键字:表示某个对象。用来访问本类成员。
(1)this可以出现在实例方法和构造方法中,但不能出现在类方法(静态方法)中,但是可以使用类名来访问静态成员,如下。。
(2)因为实例方法一定是对象来调用,当一个对象调用实例方法时,那么该实例方法中的this就代表当前正在调用该方法的对象。
class AAA{
static int c;
static void set(int b)
{
AAA.c=b;//不能使用this.c=b;
}
}
-
包:类似与文件夹。包语句:package。
(1)用【.】分隔。作为源文件的第一条语句。
(2)按照包名形成的目录来存放字节码文件。 -
import语句:引入包中的类。不引入包,则写类的全称。
(1)引入自定义包:把程序使用的自定义的包所形成的目录都放在同一文件夹中,import引入即可。 -
访问权限:是指对象是否可以通过【.】运算符去操作自己的变量或方法。private,public、protected、友好。
(1)注意:在编写类的时候,类中的实例方法总是可以操作该类中的实例变量和类变量、类方法总是可以操作自己的类变量,与修饰符无关。
(2)友好类:在没有写访问权限时,它就默认是友好访问权限,又称为包访问权限。 -
不同包不能访问友好类,即使引入也不行。
-
基本类型的类封装:Byte、Integer、Short、Long、Float、Double和Character类。Character中有很多实用的类,类似于C中的String.h头文件的作用。
-
对象数组:数组元素的对象。
(1)创建对象数组:例:Demo [] arr = new Demo[10];
,这只是创建了对象的数组,即:每个对象还都是空对象,还需要为每个对象分配内存空间。
(2)创建对象:例:arr[0] = new Demo();
。
第四章 子类与继承
子类与父类
子类的继承性
子类与对象
成员变量的隐藏于方法重写
super关键字
final关键字
对象的上转型对象
继承于多态
abstract类和abstract方法
面向抽象编程
开闭原则
子类与父类
- 子类可以让我们不必一切“从头开始”。使用extends关键字继承父类。
- 语法:
class A extends B{
……
}
- java不支持多重继承,一个子类只有一个父类。
- java中的类形成树形结构,根节点就是Object类。
子类的继承性
-
子类和父类在同一个包时:
(1)子类继承其父类中不是private的成员作为自己的成员。 -
子类和父类不在同一个包时
(1)子类只继承父类中protected和public访问权限的成员变量作为自己的成员变量,private和友好访问权限不会被子类继承。 -
友好型变量同包会继承,不同包不会继承。
-
protected说明:
(1)A类中有一个protected成员,在B类中定义一个A类的对象a;- 如果这个成员是继承来的,那么在A类中想要通过a对象去访问,就必须要求B类和A类的父类在同一个包下。A和B在不在同一个包下不影响。
- 如果这个成员是A类中自己定义的,只要求B类和A类在同一包下即可访问。
(2)如果一个变量不想被别的类访问,但又想让其子类访问,就可以使用protected修饰符。
子类与对象
- 有一个A类,类中有一个成员方法fun和私有成员q,这个成员方法操作了私有成员q,现在B类继承了A,B类并没有继承A类的私有成员q,但是却可以通过调用fun方法去操作私有成员。
(1)所以,在new B类对象时,也会开辟一个q的内存空间,但是B类不能直接访问,只能通过方法fun去访问。
成员变量的隐藏和方法的重写
-
当子类和父类的成员变量同名时,子类就会隐藏继承自父类的成员变量。
(1)子类对象仍然可以调用从父类继承的方法操作被子类隐藏的成员变量。即:子类继承的方法,所操作的变量一定是被子类隐藏的父类的成员变量。
(2)尽量避免隐藏父类的成员变量。 -
方法重写:如果子类可以继承父类某个方法,那么子类就有权利重写这个方法。
(1)方法重写是指子类中定义一个方法, 这个方法的类型和父类的方法的类型一致或者是父类的方法的类型的子类型(所谓子类型是指,如果父类的方法的类型是“类”,那么允许子类的重写方法的类型是“子类”,基本类型没有子类),并且这个方法的名字、参数个数、参数的类型和父类的方法完全相同。
(2)重写方法既可以操作继承的成员变量、调用继承的方法,也可以操作子类新声明的成员变量、调用新定义的其他方法, 但无法操作被子类隐藏的成员变量和方法。
(3)重写父类的方法时,不允许降低方法的访问权限,但可以提高访问权限。
-
super关键字:
(1)用super操作被隐诚的成员变量和方法:- 子类一旦隐藏了继承自父类的成员变量,那么子类创建的对象就不再拥有该变量,该变量将归关键字super所拥有,同样子类一旦隐藏了继承的方法,那么子类创建的对象就不能调用被隐藏的方法,该方法的调用由关键字
super负责。 - 因此,如果在子类中想使用被子类隐藏的成员变量或方法就需要使用关键字super。
例:super.x; super.play();
就是访问和调用被子类隐藏的成员变量x和方法play().
(2)使用super调用父类的构造方法
- 由于子类不继承父类的构造方法,因此,子类在其构造方法中需使用super来调用父类的构造方法,而且super必须是子类构造方法中的头一条语句, 即:如果在子类的构造方法中,没有明显地写出super关键字来调用
父类的某个构造方法,那么默认地有: super () :
- 子类一旦隐藏了继承自父类的成员变量,那么子类创建的对象就不再拥有该变量,该变量将归关键字super所拥有,同样子类一旦隐藏了继承的方法,那么子类创建的对象就不能调用被隐藏的方法,该方法的调用由关键字
-
final关键字:fina1关键字可以修饰类、成员变量和方法中的局部变量。
(1)final类:可以使用final将类声明为final类。fina1类不能被继承,即不能有子类。如:
final class A
{
……
}
(2)fina1方法:如果用fina1修饰父类中的一个方法,那么这个方法不允许子类重写,也就是说,不允许子类隐藏,只能老老实实的继承的final方法 (老老实实继承,不许做任何篡改)。
(3)常量:如果成员变量或局部变量被修饰为final,那它就是常量。由于常量在运行期间不允许再发生变化,所以要求程序在声明常量时必须指定该常量的值。.
对象的上转型对象
上转型对象:子类对象转为父类对象,失去一些属性和方法。(比如:老虎是动物)
上转型对象可以调用其子类对象重写的父类的方法,和子类对象调用这个重写的方法等价。但不能访问子类和父类同名的变量,它访问的是父类的被子类隐藏的那个变量。
- 上转型对象不能操作子类新增的成员变量(失掉了这部分属性),不能调用子类新增的方法(失掉了一些行为)
- 上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。
- 上转型对象操作子类继承的方法或子类重写的实例方法,其作用等价于子类对象去调用这些方法。因此,如果子类重写了父类的某个实例方法后,当对象的上转型对象调用这个实例方法时一定是调用了子类重写的实例方法
- 可以将对象的上转型对象再强制转换为一个子类对象,这事,该子类对象又具备了子类对象所有的属性和功能。
- 不能将父类创建的对象的引用赋值给子类声明的对象。
- 如果子类重写了父类的静态方法,那么子类对象的上转型对象不能调用子类重写的静态方法,只能调用父类的静态方法。
package lu;
import java.util.Scanner;
class A
{
public int m;
public int getM()
{
return m;
}
int seeM()
{
return m;
}
}
class B extends A
{
public int m;
@Override
public int getM()
{
return m+102;
}
}
public class Demo4 {
public static void main(String[] args) {
A a=new A();
B b=new B();
b.m=100;
System.out.println(b.getM());// 202
a=b;
a.m=23;
System.out.println(a.getM());//重写的方法,和子类调用等价 202
System.out.println(a.seeM());//继承的方法调用的是被隐藏的m 23
}
}
继承与多态
多态性是指:父类的某个方法被子类重写时,可以产生自己的功能行为。通过上转型对象调用这些方法时就会有很多种状态。
package lu;
class Animal
{
void cry()
{
}
}
class dog extends Animal{
@Override
void cry()
{
System.out.println("汪汪汪");
}
}
class cat extends Animal{
@Override
void cry()
{
System.out.println("喵喵喵");
}
}
public class Demo6 {
public static void main(String[] args) {
Animal animal;
animal=new dog();//animal 是 dog的上转型对象
animal.cry();
animal=new cat();
animal.cry();
}
}
抽象类和抽象方法
使用abstract关键字修饰的类,称为抽象类。如:abstract class A{……}
使用abstract关键字修饰的方法叫抽象方法,如:abstract int fun();
- 不允许使用final和abstract同时修饰一个方法和类,也不允许使用static修饰abstract方法,即:abstract方法不能是静态的。
- 抽象类可以声明对象,但不能new对象。
- 子类继承抽象类,必须实现抽象类的所有方法,否则子类也只能声明为抽象类。
- 抽象类对象可以作为上转型对象,即:只声明抽象类对象但不new。(重点)
抽象编程注重行为标准,细节交给子类完成。抽象方法只提出了标准,让之类去实现。
面向抽象编程
所谓面向抽象编程,是指当设计某种重要的类时,不让该类面向具体的类,而是面向抽象类,
即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。
面向抽象编程目的是为了应对用户需求的变化,将某个类中经常因需求变化而需要改动的代码从该类中分离出去。
面向抽象编程的核心是让类中每种可能的变化对应地交给抽象类的一个子类去负责,从而让该类的设计者不去关心具体实现,避免所设计的类依赖于具体的实现。
面向抽象编程使设计的类容易应对用户需求的变化。
《Java设计模式》一 书。
开闭原则
所谓“开-闭原则”、(Open- Closed Principle) 就是让设计的系统应当对扩展开放,对修改关闭。
怎么理解对扩展开放,对修改关闭呢?
实际上,这句话的本质是指当系统中增加新的模块时,不需要修改现有的模块。在设计系统时,应当首先考虑到用户需求的变化,将应对用户变化的部分设计为对扩展开放,而设计的核心部分是经过精心考虑之后确定下来的基本结构,这部分应当是对修改关闭的,即不能因为用户的需求变化而再发生变化,因为这部分不是用来应对需求变化的。
如果系统的设计遵守了“开-闭原则”,那么这个系统一定是易维护的,因为在系统中增加新的模块时, 不必去修改系统中的核心模块。