java 特性:分布行,跨平台性,安全行,多线程,面向对象编程,简单性
高级语言分为编译型和解释型:
编译型:整个程序写完一起编译速度快效率高解释性:需要一句解释一句编译速度慢效率低
java是两者综合:编译器(javac)先把你写好的代码编译成class文件(字节码文件)再用jvm,java虚拟机(解释器)解释执行
java基础语法
概念
类:就是一类模板对象:模板对照的具体事物 类的具体实例
方法:就是这个事物的一种 可以有多种
标识符
标识符就是用来标记类名,对象名,方法名,包名,文件名等
注意事项:
1可以用字母,下划线,$组成,不能用数字开头
2大小写敏感要分清
3不能用关键字
关键字
tish,class,int,long,double,null,true,void,final,try,return,break,do,import,等
修饰符
访问修饰符:
public 公共都可以访问,
protected表示同一个包的类可以访问,其他的包的该类的子类也可以访问。
private私人的表示只有自己能访问
非访问修饰符:
static 可以当做普通类使用,而不用先实例化一个外部类。(用他修饰后,就成了静态内部类了)。 使用对象:类、变量、方法、初始化函数(注意:修饰类时只能修饰 内部类 )
abstract: 表示是抽象类。 使用对象:类、接口、方法
final: 表示类不可以被继承。 使用对象:类、变量、方法
数据类型:一个字节站八个比特位
八大基本类型:
整数型:byte1字节(8位),short2个字节(16),int4个字节(32),long8个字节(64)
浮点型:fioat4个字节(32),double8个字节(64)
其他:boolean只有两个取值:true 和 false;char 数据类型可以储存任何字符
引用类型:类,接口,数值。
类型转化:低转高自动转换,高转低强制转化需要注意内存溢出
运算符
算术运算符:+, -, *, /, ++, --
关系运算符:>,<,>=,<=,!=
位运算符:
& 对应位上全是1才为一
| 对应位上有一个是1就是1
^ 对应位相同是0反之位1
~ 取反
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。
>>>按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充
逻辑运算符:&&与,||或,!非
赋值运算符:==,+=(A+=C,A=A+C C和A必须是统一数据类型),-=,*=,/=,(%)= 就是(C%= A等价于C = C%A)%就是取余,
<< = 左移位赋值运算符 C << = 2等价于C = C << 2,>> = 右移位赋值运算符
&= 按位与赋值运算符 C&= 2等价于C = C&2
^ = 按位异或赋值操作符 ,| = 按位或赋值操作符
条件运算符 (三元运算符): “?:”
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 );
}
}
interesting运算符:运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。
用法
class Vehicle {}
public class Car extends Vehicle {
public static void main(String[] args){
Vehicle a = new Car();
boolean result = a instanceof Car;
System.out.println( result);
}
}
循环语句
whlie循环 :只要布尔表达式为 true,循环就会一直执行下去。
while( 布尔表达式 ){ //循环内容 }
do .whlie循环:跟whlie循环一样不过前面有一个do是必须执行一次的代码区域,代码区在whlie前面
do {//代码语句 }while(布尔表达式);
for循环:
for(初始化; 布尔表达式; 更新) {//代码语句 }
- 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
- 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量。
- 再次检测布尔表达式。循环执行上面的过程。
增强for循环:可以直接用表达式进行
for(声明语句 : 表达式) {//代码句子 }
int [] numbers = {10, 20, 30, 40, 50};for(int x : numbers ){System.out.print( x );System.out.print(",");}System.out.print("\n");String [] names ={"James", "Larry", "Tom", "Lacy"};for( String name : names ) {System.out.print( name );System.out.print(",");}
循环语句中常用的关键字
break :主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
continue:跳过这轮循环
条件语句
if:
if(布尔表达式) {//如果布尔表达式为true将执行的语句 }
if-else:
if(布尔表达式){//如果布尔表达式的值为true }else{//如果布尔表达式的值为false }
if-else-if-else:
if(布尔表达式 1){//如果布尔表达式 1的值为true执行代码 }else if(布尔表达式 2){//如果布尔表达式 2的值为true执行代码 }else if(布尔表达式 3){//如果布尔表达式 3的值为true执行代码 }else {//如果以上布尔表达式都不为true执行代码 }
switch case语句
switch(expression){case value ://语句break; //可选case value ://语句break; //可选//你可以有任意数量的case语句default : //可选//语句 }
面向对象:现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装。
面向对象编程的本质就是以类的方式组织代码一对象的方式封装数据
为什么要学习面向对象:为了解决项目中复杂的问题 可以是多人一起进行是自下而上的编写 。适用于大型复杂系统,方便复用、
怎么用:在java中主要以对象的思想进行
方法:
什么是方法:方法是为了解决一类为问题的有序集合解,他在类中或者对象中。方法一般是被调用
方法的语法:修饰符 返回值类型 方法名(参数类型 参数名){
...方法体...return 返回值; }
public static void test(string name,int age){
}
例:
/** 返回两个整型变量数据的较大值 */ public static int max(int num1, int num2) {int result;if (num1 > num2)result = num1;elseresult = num2;return result; }
方法调用:看有没有返回值
有返回值:方法调用通常被当做一个值 int larger = max(30, 40);
没有返回值:
例
public class TestVoidMethod {public static void main(String[] args) {
//调用方法printGrade(78.5);}public static void printGrade(double score) {if (score >= 90.0) {System.out.println('A');}else if (score >= 80.0) {System.out.println('B');}else if (score >= 70.0) {System.out.println('C');}else if (score >= 60.0) {System.out.println('D');}else {System.out.println('F');}} }
值传递和引用传递
java中基本数据类型都是值传递
对象是引用传递 但是本质也是值传递 传递的是对象的地址
方法的重载
在同一个类中方法可以命名一样但是入参必须不一样 程序可以根据你的入参来判断你使用的是那个方法
命令行传参
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
命令行参数是在执行程序时候紧跟在程序名字后面的信息。
public class CommandLine {public static void main(String[] args){ for(int i=0; i<args.length; i++){System.out.println("args[" + i + "]: " + args[i]);}} }
$ javac CommandLine.java
$ java CommandLine this is a command line 200 -100
args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
构造方法
当一个对象被创建,构造方法可以初始化这个对象,构造方法和类名相同但是没有返回值。
通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。
你是否定义构造方法,所有类都有默认的构造方法初始化为0
因为 Java 自动提供了一个默认构造方法,默认构造方法的访问修饰符和类的访问修饰符相同(类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected)。 你自己定义构造方法默认面对就会失效
// 一个简单的构造函数 class MyClass {int x;// 以下是构造函数 MyClass() {x = 10;} }
封装
程序追求高内聚低耦合。
在一个类中属性私有
给他开放几个特定方法接口
1什么是封装:1就是吧对象的属性和行为紧密相连成一个整体
2隐藏信息只留你想让别的类想看到的信息
2为什么用封装:1良好的封装能够减少耦合,符合程序设计追求“高内聚,低耦合”
2类内部的结构可以自由修改。可以对成员变量进行更精确的控制 ,
3隐藏信息
3怎么用:如下
1 package test0; 2 //封装list类给属性私有,用get set方法操作属性 3 public class ListDTO { 4 //行 5 private int row; 6 //列 7 private int col; 8 //值 9 private int value; 10 public int getValue() { 11 return value; 12 } 13 14 public int getRow() { 15 return row; 16 } 17 18 public int getCol() { 19 return col; 20 } 21 22 public void setRow(int row) { 23 this.row = row; 24 } 25 26 public void setValue(int value) { 27 this.value = value; 28 } 29 30 public void setCol(int col) { 31 this.col = col; 32 } 33 }
继承
1什么是继承:
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
java中只有子类可以继承父类 一个父类可以被多个子类继承
例猫类可以继承动物类狗类也可以继承动物类
子类可以继承父类的所有public方法
2为什么要用继承:
(1)提高类代码的复用性
(2)提高了代码的维护性
(3)使得类和类产生了关系,是多态的前提(它也是继承的一个弊端,类的耦合性提高了)
3怎么用:如下
类继承的格式
class 父类 { }
class 子类 extends 父类 { }
继承是为了减少代码的冗余
1 package test0; 2 //父类 3 public class Animal { 4 String name="zhaoKeMing"; 5 private int id; 6 7 public void eat(){ 8 System.out.println(name+"正在吃"); 9 } 10 public void sleep(){ 11 System.out.println(name+"正在睡"); 12 } 13 public void introduction() { 14 System.out.println("大家好!我是" + id + "号" + name + "."); 15 } 16 }
1 package test0; 2 //子类 3 public class Penguin extends Animal{ 4 private String name="赵可明"; 5 public void test(String name){ 6 //子类的name 赵可明 7 System.out.println("这个是继承子类的的name:"+this.name); 8 //父类法的name 9 System.out.println("这个是继承父类的name:"+super.name); 10 } 11 }
1 import test0.Penguin; 2 //主方法 3 public class main { 4 public static void main(String[] args) { 5 String name="赵小帅"; 6 //实例化子类 7 Penguin penguin =new Penguin(); 8 //调用子类的方法 9 penguin.test(name); 10 //也可以通过子类调用父类的public方法 11 penguin.eat(); 12 } 13 }
运行结果
这个是继承子类的的name:赵可明
这个是继承父类的name:zhaoKeMing
zhaoKeMing正在吃
super关键字
就是可以在子类点出父类的public方法和属性
this是指向本类的super是指向父类的
方法的重写
重写是在继承关系下子类重写父类的public方法
1 package test0; 2 //子类 3 public class Penguin extends Animal{ 4 private String name="赵可明"; 5 public void test(String name){ 6 //子类的name 赵可明 7 System.out.println("这个是继承子类的的name:"+this.name); 8 //父类法的name 9 System.out.println("这个是继承父类的name:"+super.name); 10 } 11 //重写父类Animal类的eat方法 12 @Override 13 public void eat(){ 14 System.out.print("这个是重写父类的方法"); 15 } 16 }
重写就在在父类方法的基础上进行修改成你自己需要的方法
多态
1什么是多态:
多态就是在父类跟子类都有相同的方法程序具体调哪一个需要等程序运行的才能知道 具有一定的动态性
通俗点讲,多态就是不同对象对同一物体或事件发出不同的反应或响应。比如stuendt是一个父类,那么在操场上上体育课的学生和在教室里面的学生就是它的子类。
这时上课铃声响了,上体育课的学生去操场,在教室里面上课的学生则是回教室,不同的学生有着不同的反应,这就是多态。
2为什么要用多态
1)提高了代码的维护性 (通过继承和实现来保证)
2)提高了代码的扩展性 (通过多态来保证)
3)降低代码耦合度
3怎么用:
1 // 上代码 2 public class Animal { 3 public String name = "animal"; 4 5 @Override 6 public void eat(){ 7 System.out.println("动物吃东西!"); 8 } 9 } 10 11 public class Tiger extends Animal { 12 public String name = "tiger"; 13 14 @Override 15 public void eat() { 16 System.out.println("虎吃鸡!"); 17 } 18 19 public void run() { 20 System.out.println("虎奔跑!"); 21 } 22 } 23 24 public class Snake extends Animal { 25 public String name = "snake"; 26 27 @Override 28 public void eat() { 29 System.out.println("蛇吞象!"); 30 } 31 32 public void run() { 33 System.out.println("蛇爬行!"); 34 } 35 }
1.多态成员变量:编译检查的时候检查Animal类中是否有此变量定义Animal tiger = new Tiger(); System.out.println("name = " + tiger.name); // name 是Animal中的值,编译期只能取到父中的值上述打印输出结果为: name = Animal2.使用多态调用成员方法:编译时检查左边类型,运行时实际调用右边对象Animal snake = new Snake();System.out.println(sanke.eat()); // snake 的门面类型是 Animal, 但实际类型是Snake, 所以运行时调用的是Snake中重写后的方法。打印输出结果为: 蛇吞象!
3.2、多态的转型和instanceof关键字
多态的转型分为向上转型和向下转型两种向上转型:多态本身就是向上转型过的过程使用格式:父类类型 变量名=new 子类类型();适用场景:当不需要面对子类类型时,通过提高扩展性,或者使用父类的功能就能完成相应的操作。Amimal tiger = new Tiger();tiger.run(); // 这样写会报错,因为编译检查tiger是Animal类型,Animal中没有run方法。 ((Snake)tiger).run(); // 此时编译检查能通过,但是运行时会报错,因为tiger实际类型是Tiger类型, 此时强制类型转换成Snake,编译时检测tiger是Animal类型,Snake也是Animal的子类,所以编译时无法发现老虎不能转化为蛇类型。 //判断tiger是不是Tiger类型if (tiger instanceof Tiger) {((Tiger) tiger).run() // 此时经过instanceof判断后才能进行强制类型转换,编译和运行时均能通过。 } 作用:用来判断某个对象是否属于某种数据类型。
package 多态;public class main {public static void main(String[] args) {//demo继承关系//1>2//1>3>4Demo01 demo01 = new Demo01();Demo02 demo02 = new Demo02();Demo03 demo03 = new Demo03();Demo04 demo04 = new Demo04();//判断Demo01是否是Demo01类型System.out.println(demo01 instanceof Demo01);//trueSystem.out.println(demo01 instanceof Demo02);//falseSystem.out.println(demo01 instanceof Demo03);//falseSystem.out.println(demo01 instanceof Demo04);//falseSystem.out.println("=================================================");System.out.println(demo02 instanceof Demo01);//trueSystem.out.println(demo02 instanceof Demo02);//true // System.out.println(demo02 instanceof Demo03);//编译错误 // System.out.println(demo02 instanceof Demo04);//编译错误System.out.println("=================================================");System.out.println(demo03 instanceof Demo01);//true // System.out.println(demo03 instanceof Demo02);//编译错误System.out.println(demo03 instanceof Demo03);//trueSystem.out.println(demo03 instanceof Demo04);//falseSystem.out.println("=================================================");System.out.println(demo04 instanceof Demo01);//true // System.out.println(demo04 instanceof Demo02);//编译错误System.out.println(demo04 instanceof Demo03);//trueSystem.out.println(demo04 instanceof Demo04);//true// 结论没有关系的引用类型编译报错,父类不是子类的数据类型,子类一定是父类的数据类型 } }
案例
// 上代码 public class Keeper {public void feed(Animal animal){animal.eat();} }public class Test {public static void main(String[] args) {Keeper GodXiu = new Keeper();Animal snake = new Snake();Animal tiger = new Tiger();GodXiu.feed(snake);GodXiu.feed(tiger);} }
个人思考总结
目前在日常开发中经常使用多态的地方就是使用集合的时候:
List list = new ArrayList();Map map = new HashMap();
抽象类和抽象方法
1什么是抽象类和抽象方法:
用abstract修饰的类是抽象类 抽象类里可以写抽象方法也可以写普通方法(抽象方法是有方法名和方法类型没有方法的实现)
子类继承抽象类需要重写抽象类中所有抽象方法
抽象类不能被实例化: Demo01 demo01 = new Demo01(); //编译错误
抽象类和抽象方法格式:
package 抽象类;public class Demo02 extends Demo01{@Overridepublic void test() {System.out.println("这个是02的重写抽象类01的test方法");} }
接口
普通类:有具体的实现
抽象类:有规范也有实现(可以写具体的方法也可以写抽象方法)
接口:只有规范不能写具体的实现
1什么是接口
接口比抽象类更抽象的 接口无法被实例化,
抽象类和接口的区别
- 1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2为什么要有接口
一个类只能继承一个父类,但是可以继承N个接口。
接口的目的是指明相关或者不相关类的多个对象的共同行为,跟抽象类很相似,可以说接口是更加抽象的抽象类。
接口体现了程序设计的多态和高内聚低耦合的设计思想。
3接口的用法如下
用intreface 声明接口
1 package 接口; 2 3 public interface Demo01 { 4 5 public void add(); 6 7 public void delete(); 8 9 }
用implements继承接口
1 package 接口; 2 3 public class Demo02 implements Demo01 { 4 @Override 5 public void add() { 6 System.out.println("这个是Demo01接口约束add方法的具体实现"); 7 } 8 9 @Override 10 public void delete() { 11 System.out.println("这个是Demo01接口约束delete方法的具体实现"); 12 } 13 }
接口不能被实例化
在 JDK1.8,允许我们给接口添加两种非抽象的方法实现:
1、默认方法,添加 default 修饰即可;
2、静态方法,使用 static 修饰;示例如下:
interface Test{//这个是默认方法default String get(String aa){System.out.println("我是jdk1.8默认实现方法...");return "";} //这个是静态方法 static void staticmethod(){System.out.println("我是静态方法");}
}
调用得话,静态方法只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用,default 方法只能通过接口实现类的对象来调用。
内部类
1什么是内部类
就是在a类里面定义一个b类 那么a就是b的外部类 b是a的内部类
内部类可分为
成员内部类
静态内部类
局部内部类
匿名内部类
2为什么要用内部类
使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响
也就是说内部类拥有类的基本特征。(eg:可以继承父类,实现接口。)在实际问题中我们会遇到一些接口无法解决或难以解决的问题,此时我们可以使用内部类继承某个具体的或抽象的类,间接解决类无法多继承引起的一系列问题。(注:内部类可以嵌套内部类,但是这极大的破坏了代码的结构,这里不推荐使用。)
除了上面的优点之外还有如下四点:
1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
2、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
3、内部类提供了更好的封装,除了该外围类,其他类都不能访问。
4、创建内部类对象的时刻并不依赖于外围类对象的创建。
3如何用:
成员内部类:
1 /** 2 * 外部类、成员内部类的定义 3 */ 4 public class Outer { 5 6 private int outerVariable = 1; 7 private int commonVariable = 2; 8 private static int outerStaticVariable = 3; 9 //省略getter/setter 10 11 /** 12 * 成员方法 13 */ 14 public void outerMethod() { 15 System.out.println("我是外部类的outerMethod方法"); 16 } 17 18 /** 19 * 静态方法 20 */ 21 public static void outerStaticMethod() { 22 System.out.println("我是外部类的outerStaticMethod静态方法"); 23 } 24 25 /** 26 * 内部类 27 */ 28 public class Inner { 29 30 private int commonVariable = 20; 31 32 /** 33 * 构造方法 34 */ 35 public Inner() { 36 } 37 38 /** 39 * 成员方法,访问外部类信息(属性、方法) 40 */ 41 public void innerShow() { 42 //当和外部类冲突时,直接引用属性名,是内部类的成员属性 43 System.out.println("内部的commonVariable:" + commonVariable); 44 //内部类访问外部属性 45 System.out.println("outerVariable:" + outerVariable); 46 //当和外部类属性名重叠时,可通过外部类名.this.属性名 47 System.out.println("外部的commonVariable:" + Outer.this.commonVariable); 48 System.out.println("outerStaticVariable:" + outerStaticVariable); 49 //访问外部类的方法 50 outerMethod(); 51 outerStaticMethod(); 52 } 53 } 54 55 /** 56 * 外部类访问内部类信息 57 */ 58 public void outerShow() { 59 Inner inner = new Inner(); 60 inner.innerShow(); 61 } 62 }
1 /* 2 * 其他类使用成员内部类 3 */ 4 public class Other { 5 6 public static void main(String[] args) { 7 //外部类对象 8 Outer outer = new Outer(); 9 //创造内部类对象 10 Outer.Inner inner = outer.new Inner(); 11 inner.innerShow(); 12 /* 13 * 可在Outer中定义get方法,获得Inner对象,那么使用时,只需outer.getInnerInstance()即可。 14 * public Inner getInnerInstance(Inner类的构造方法参数){ 15 * return new Inner(参数); 16 * } 17 */ 18 } 19 }
4、小结:【成员内部类当成Outer的成员信息存在 】
可以是任何的访问修饰符。
内部类的内部不能有静态信息。
内部类也是类,该继承继承,该重写重写,该重载重载,this和super随便用。
外部类如何访问内部类信息,必须new之后打点访问。
内部类可以直接使用外部类的任何信息,如果属性或者方法发生冲突,调用外部类.this.属性或者方法。
其它类如何访问内部类:
Outer outer=new Outer();//创造内部类对象Outer.Inner inner=outer.new Inner();inner.inner_show();
静态内部类
/*** 外部类、内部类定义*/ public class Outer {private int outerVariable = 1;/*** 外部类定义的属性(重名)*/private int commonVariable = 2;private static int outerStaticVariable = 3;static {System.out.println("Outer的静态块被执行了……");}/*** 成员方法*/public void outerMothod() {System.out.println("我是外部类的outerMethod方法");}/** 静态方法*/public static void outerStaticMethod() {System.out.println("我是外部类的outerStaticMethod静态方法");}/*** 静态内部类*/public static class Inner {/*** 成员信息*/private int innerVariable = 10;private int commonVariable = 20;static {System.out.println("Outer.Inner的静态块执行了……");}private static int innerStaticVariable = 30;/*** 成员方法*/public void innerShow() {System.out.println("innerVariable:" + innerVariable);System.out.println("内部的commonVariable:" + commonVariable);System.out.println("outerStaticVariable:"+outerStaticVariable);outerStaticMethod();}/*** 静态方法*/public static void innerStaticShow() {//被调用时会先加载Outer类 outerStaticMethod();System.out.println("outerStaticVariable"+outerStaticVariable);}}/*** 外部类的内部如何和内部类打交道*/public static void callInner() {System.out.println(Inner.innerStaticVariable);Inner.innerStaticShow();} }
1 public class Other { 2 3 public static void main(String[] args) { 4 //访问静态内部类的静态方法,Inner类被加载,此时外部类未被加载,独立存在,不依赖于外围类。 5 Outer.Inner.innerStaticShow(); 6 //访问静态内部类的成员方法 7 Outer.Inner oi = new Outer.Inner(); 8 oi.innerShow(); 9 } 10 }
4、小结【和成员内部类对比理解(区别异同)】
内部可以包含任意的信息。
静态内部类的方法只能访问外部类的static关联的信息。
利用 外部类.内部类 引用=new 外部类.内部类(); 然后利用引用.成员信息(属性、方法)调用。
访问内部类的静态信息,直接外部类.内部类.静态信息就可以了。
静态内部类可以独立存在,不依赖于其他外围类。
局部内部类
1 /** 2 * 外部类、内部类 3 */ 4 public class Outer { 5 /** 6 * 属性和方法 7 */ 8 private int outerVariable = 1; 9 /** 10 * 外部类定义的属性 11 */ 12 private int commonVariable = 2; 13 /** 14 * 静态的信息 15 */ 16 private static int outerStaticVariable = 3; 17 18 /** 19 * 成员外部方法 20 */ 21 public void outerMethod() { 22 System.out.println("我是外部类的outerMethod方法"); 23 } 24 25 /** 26 * 静态外部方法 27 */ 28 public static void outerStaticMethod() { 29 System.out.println("我是外部类的outerStaticMethod静态方法"); 30 } 31 32 /** 33 * 程序的入口 34 */ 35 public static void main(String[] args) { 36 Outer outer = new Outer(); 37 outer.outerCreatMethod(100); 38 } 39 40 /** 41 * 成员方法,内部定义局部内部类 42 */ 43 public void outerCreatMethod(int value) { 44 /** 45 * 女性 46 */ 47 boolean sex = false; 48 49 /** 50 * 局部内部类,类前不能有访问修饰符 51 */ 52 class Inner { 53 54 private int innerVariable = 10; 55 private int commonVariable = 20; 56 /** 57 * 局部内部类方法 58 */ 59 public void innerShow() { 60 System.out.println("innerVariable:" + innerVariable); 61 //局部变量 62 System.out.println("是否男性:" + sex); 63 System.out.println("参数value:" + value); 64 //调用外部类的信息 65 System.out.println("outerVariable:" + outerVariable); 66 System.out.println("内部的commonVariable:" + commonVariable); 67 System.out.println("外部的commonVariable:" + Outer.this.commonVariable); 68 System.out.println("outerStaticVariable:" + outerStaticVariable); 69 outerMethod(); 70 outerStaticMethod(); 71 } 72 } 73 //局部内部类只能在方法内使用 74 Inner inner = new Inner(); 75 inner.innerShow(); 76 } 77 }
3、小结【局部内有很多局限,应注意作用域】
- 类前不能有访问修饰符。
- 仅在此方法内使用。
- 无法创造静态信息。
- 可以直接访问方法内的局部变量和参数(有限制,下面详谈),但是不能更改。
- 可以随意的访问外部类的任何信息。
匿名内部类
/** * 接口中方法默认为public */ public interface IAnimal{void speak(); }
1 /** 2 * 外部内、内部类 3 */ 4 public class Outer { 5 6 public static IAnimal getInnerInstance(String speak){ 7 return new IAnimal(){ 8 @Override 9 public void speak(){ 10 System.out.println(speak); 11 }}; 12 //注意上一行的分号必须有 13 } 14 15 public static void main(String[] args){ 16 //调用的speak()是重写后的speak方法。 17 Outer.getInnerInstance("小狗汪汪汪!").speak(); 18 } 19 }
3、结果
小狗汪汪汪!
4、小结【匿名内部类常常被用来重写某个或某些方法】
- 匿名内部类是没有访问修饰符的。
- 使用匿名内部类时,这个new之后的类首先是要存在的,其次我们要重写new后的类的某个或某些方法。
- 匿名内部类访问方法参数时也有和局部内部类同样的限制。
- 匿名内部类没有构造方法。
异常
1什么是异常:
在 Java 中,异常处理是一种重要的编程概念,用于处理程序执行过程中可能出现的错误或异常情况。
异常发生的原因有很多,通常包含以下几大类:
- 用户输入了非法数据。
- 要打开的文件不存在。
- 网络通信时连接中断,或者JVM内存溢出。
这些异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的。
要理解 Java 异常处理是如何工作的,你需要掌握以下三种类型的异常:
-
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这些异常在编译时强制要求程序员处理。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
这类异常通常使用 try-catch 块来捕获并处理异常,或者在方法声明中使用 throws 子句声明方法可能抛出的异常。
try {// 可能会抛出异常的代码 } catch (IOException e) {// 处理异常的代码 }
public void readFile() throws IOException {// 可能会抛出IOException的代码 }
运行时异常: 这些异常在编译时不强制要求处理,通常是由程序中的错误引起的,例如 NullPointerException、ArrayIndexOutOfBoundsException 等,这类异常可以选择处理,但并非强制要求。
try {// 可能会抛出异常的代码 } catch (NullPointerException e) {// 处理异常的代码 }
错误
错误不是异常,而是脱离程序员控制的问题,错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
Java 提供了以下关键字和类来支持异常处理:
- try:用于包裹可能会抛出异常的代码块。
- catch:用于捕获异常并处理异常的代码块。
- finally:用于包含无论是否发生异常都需要执行的代码块。
- throw:用于手动抛出异常。
- throws:用于在方法声明中指定方法可能抛出的异常。
- Exception类:是所有异常类的父类,它提供了一些方法来获取异常信息,如 getMessage()、printStackTrace() 等。
Exception 类的层次
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
Exception异常
Error错误(错误jvm虚拟机会自己处理)
在 Java 内置类中(接下来会说明),有大部分常用检查性和非检查性异常。
Java 内置异常类
Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
Java 根据各个类库也定义了一些其他的异常,下面的表中列出了 Java 的非检查性异常。
异常 | 描述 |
---|---|
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
下面的表中列出了 Java 定义在 java.lang 包中的检查性异常类。
异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
异常方法
下面的列表是 Throwable 类的主要方法:
序号 | 方法及说明 |
---|---|
1 | public String getMessage() 返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 |
2 | public Throwable getCause() 返回一个 Throwable 对象代表异常原因。 |
3 | public String toString() 返回此 Throwable 的简短描述。 |
4 | public void printStackTrace() 将此 Throwable 及其回溯打印到标准错误流。 |
5 | public StackTraceElement [] getStackTrace() 返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 |
6 | public Throwable fillInStackTrace() 用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 |
捕获异常
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try
{// 程序代码
}catch(ExceptionName e1)
{//Catch 块
}
Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数的方法是一样