前言:基本变量OK,基本语句(for if while)OK,输入输出OK,集合OK
单例模式
设计模式:对问题行之有效的解决办法
单例设计模式:保证一个类在一个内存中的对象唯一性
如何保证对象唯一性:
- 不允许其他程序用new创建该类对象
- 在该类创建一个本类实例
- 对外提供一个方法让其他程序可以获取该对象
步骤:
- List item
- 私有化该类的构造函数
- 通过new在奔雷中创建一个本类对象
- 定义一个共有的方法,将创建的对象返回
package com.yyxx.day08;
import java.util.Arrays;
import org.junit.Test;
//饿汉式单例模式
class Single{
//类一加载,对象就已经存在了
static Single single=new Single();
private Single() {
// TODO Auto-generated constructor stub
}
public static Single getInstance() {
return single;
}
}
//懒汉式单例模式
class Single2{
//类加载进来 没有对象 只有调用了getInstance方法时,才会创建对象
//延迟加载模式
private static Single2 single=null;
private Single2() {
}
public static Single2 getInstance() {
if(single==null)
single=new Single2();
return single;
}
}
class SingleDemo {
public static void main(String[] args) {
Single s1=Single.single;
Single s2=Single.single;
System.out.println(s1==s2);
}
}
class Test{
private int num;
private static Test test=new Test();
private Test() {
}
public void setNum(int num) {
this.num=num;
}
private int getnum() {
// TODO Auto-generated method stub
return num;
}
}
面向对象
继承extends
**单继承:**一个子类只能有一个父类
**多继承:**一个之类有多个父类(Java不支持,对C++的多继承进行了改良),多个父类中的相同成员会产生调用不确定性
多重继承:太爷爷->爷爷->爸爸->儿子->孙子
形式:
public class <子类名> extends <父类名> {
<代码段>
}
重载vs重写
**重写:**子类的函数与分类函数一样,运行子类的函数,为重写(覆盖)
class Fu
{
void show() {
System.out.println("FUFUFUFUFU");
}
}
class Zi extends Fu
{
void show() {
System.out.println("ZIZIZIZIZI");
}
}
class FuZiDemo{
public static void main(String[] args) {
Zi zi=new Zi();
zi.show();
}
}
结果为
ZIZIZIZIZI
#前提1:子类权限要大于等于父类
比如将上述代码中的父类函数改为:
public void show()
程序会有错误
private-> ->public
#前提2:被覆盖或者覆盖的方法的对象不能非静态
**重载:**在同一类中的相同函数名,参数不一样
构造函数
构造子类对象时,父类的构造函数也会运行
原因:子类构造器函数中第一行有一个默认的隐式语句:super(),调用父类中空参数的构造函数
class Fu
{
/*public static void show() {
System.out.println("FUFUFUFUFU");
}*/
public Fu() {
System.out.println("FUFUFUFUFU");
}
Fu(int x){
System.out.println("Fu:"+x);
}
}
class Zi extends Fu
{
//super(); //调用父类中空参数的构造函数
/*public static void show() {
System.out.println("ZIZIZIZIZI");
}*/
public Zi() {
System.out.println("ZIZIZIZIZI");
}
Zi(int x){
System.out.println("Zi:"+x);
}
}
class FuZiDemo{
public static void main(String[] args) {
// Zi zi=new Zi();
// zi.show();
new Zi();
new Zi(6);
}
}
结果为:
FUFUFUFUFU
ZIZIZIZIZI
FUFUFUFUFU
Zi:6
final关键字
继承的弊端:打破函数的封装
final关键字:避免被继承
- 修饰符,可以修饰类,方法,变量
- 修饰的类不可以被继承
- 修饰的方法不能被覆盖
- 修饰的变量是个常量,只能赋值一次
——写法规范:常量所有字母都大写,多个单词中间用下划线_隔开
抽象类abstract关键字
子类的方法概括,具体实现在各个子类中
形式:
abstract class <父类>
{
<返回数据类型> <方法名>();
}
class <子类>
{
<返回数据类型> <方法名>()
{
<代码段>
}
}
抽象类的特点:
- 方法只有声明没有实现时,该方法为抽象方法,需要被abstract修饰
- 抽象方法必须定义在抽象类中,该类也必须用abstract修饰
- 抽象类不能被实例化——因为调用抽象方法没有意义
- 抽象类必须其子类覆盖所有的抽象方法后,该子类才可以实例化,即抽象类中的方法都要有实现方式,否则盖子类为抽象类
- 抽象类中有构造函数——用于给子类对象进行初始化
- 抽象类可以不定义抽象方法,但是一般不会
- 与抽象类关键字不能共存的关键字
1> private
2> static
3> final
abstract class Fu {
//与抽象类关键字不能共存的关键字:private、static、final
int a;
//abstract private int b; //不可行
private int b;
Fu() { //构造函数
a=0;
}
abstract void show();
abstract void write();
void read() { //可以有非抽象方法
}
}
class Zi extends Fu{
@Override
void show() {
System.out.println("show");
}
@Override
void write() {
System.out.println("write");
}
}
public class Demo04{
public static void main(String[] args) {
Zi zi=new Zi();
System.out.println(zi.a);
zi.show();
zi.write();
}
}
- 抽象类和一般类
1> 相同点:都是用来描述事物,都在内部定义了成员
2> 不同点:一般类有足够的信息描述事物,抽象类则可能不足;一般类中不能定义抽象方法,抽象类中则可以定义抽象方法,也可以定义非抽象方法
3> 一般类可以被实例化,抽象类不行 - 抽象类一定是父类——因为需要子类覆盖其方法后才可以对子类实例化
接口Interface
抽象类中的方法全是抽象方法——接口Interface,非class
成员:
- 全局常量 public static final
- 抽象方法 public abstract
接口中的成员全是public的(公共权限),否则无法被调用
类与接口的继承(实现):
class <类名> implements <接口名>{}
接口无法实例化
接口的存在——多实现,是由于多继承的调用不确定性
class <类名> implements <接口名1>,<接口名2>,… {}
要求:
1.接口中的方法,若方法名相同,返回值类型要相同
2.包含的接口中的所有方法都要包含
3.接口可以继承接口,但不能实现接口
interface DemoA{
//全是抽象方法 interface代替class
//public static final int a=0;
public void show();
//public abstract void write();
}
interface DemoB{
public void write();
}
interface DemoImp1 extends DemoB{
//代码段
}
class DemoImp implements DemoA,DemoB{
@Override
public void show() {
System.out.println("show");
}
@Override
public void write() {
// TODO Auto-generated method stub
}
/*@Override
public void write() {
System.out.println("write");
}*/
}
class InterfaceDemo{
public static void main(String[] args) {
DemoImp demoImp=new DemoImp();
//System.out.println(DemoImp.a);
demoImp.show();
//demoImp.write();
}
}
接口特点:
- 对外暴露的规则
- 程序的功能扩展
- 降低耦合性
- 多实现
- 类与接口是实现关系,类可以继承类并实现多个接口
- 接口可以继承接口
接口VS抽象类:
相同点:向上抽取
不同点:1. 抽象类需要被继承-单继承;接口只需要被实现,可以多实现
2. 抽象类中可以定义抽象方法和非抽象,接口中只能定义抽象方法,且必须有子类实现
3. 抽象类的继承是定义该体系的基本共性内容;接口是定义题词的额外功能
多态
后期可以运用前期的代码,前期不可以运用后期的代码
向上造型:<父类名> a = new <子类名>();
——只能调用父类中的共用方法
向下造型:<子类名> b =(<子类名>) a;
——使用子类中的特有方法
判断对象类型:instanceof
多态的成员的特点:
- 成员变量
一般造型:引用本类中的变量的值
向上造型:引用父类中的变量的值
向下造型:引用子类中的变量的值
简单说:编译和运行都参考等号左边 - 成员函数
编译看左边,运行看右边 - 静态函数
看左边
public class Demo01 {
public static void main(String[] args) {
// 创建子类对象,会先创建父类对象(调用父类的构造器)
Dog d=new Dog();
// d.eat();
//向上造型- 自动类型转换
Animal a=new Dog();
a =new Pig();
//a只能调用Animal中定义过的成员变量和方法
a.eat(); //在Dog中有eat Pig中也有eat 最终运行的是重写的方法
boolean c=(a instanceof Dog);
if(c) System.out.println("true");
if(a instanceof Dog) { //a引用是不是Dog类型的对象
//a instanceof Dog=false
//强制类型转换
//一般来说,所有的父类都可以强制转换成子类 语法无问题
Dog d1=(Dog)a;
//ClassCastException 类转换异常
d1.wang();
}
}
}
匿名内部类
内部类:定义在另一个类里面或者一个方法里面的类,可以直接访问外部类的成员,包括私有成员 #但是外部类要访问内部类中的成员必须建立内部类的对象
public class InnerDemo {
int a;
InnerDemo() { //构造器
a=0;
}
class Inner{ //内部类
int b;
Inner() {
b=1;
}
void show() {
//内部类可以直接访问外部类的成员
System.out.println("内部调用外部:外部的a="+a);
}
void create() {
System.out.println("Creating...");
}
}
void method() {
//外部类要访问内部类,必须先建立内部类对象
Inner inner =new Inner();
inner.show();
System.out.println(inner.b);
}
public static void main(String[] args) {
InnerDemo outer =new InnerDemo();
outer.method();
Inner inner1 = outer.new Inner();
inner1.create();
/*程序运行结果
内部调用外部:外部的a=0
1
Creating...
*/
}
}
成员内部类:直接一个类的内部
局部内部类:定义在外部类的一个方法或者一个作用域里面
public class InnerDemo2 {
public static void main(String[] args) {
new Outer().method();
}
}
class Outer {
int num = 3;
void method() {
class Inner {
void show() {
System.out.println("show Outer's num:"+num);
}
}
//内部类可以放在局部位置上
Inner inner = new Inner();
inner.show();
}
}
匿名内部类:内部类的简写格式,没有名字,所以没有构造器——前提:必须继承或者实现一个外部类或者接口
静态内部类:static修饰的内部类
匿名内部类格式:
外部:
abstract class <类名>{
抽象方法;
}
内部:
new <类名>()
{
方法实现;
}
public class InnerDemo3 {
//匿名内部类的前提:必须继承或者实现一个外部类或者接口
public static void main(String[] args) {
new Outer1().method();
}
}
abstract class abs{
abstract void show();
}
class Outer1{
int num=4;
class Inner1 extends abs{
void show() {
System.out.println("show Outer's num:"+num);
}
}
void method() {
new Inner1().show();
}
}
应用场景:
当函数参数是接口类型时,而且接口中的方法不超过三个时,可以用匿名内部类作为实际参数进行传递
总结:
public class InnerDemo4 {
//匿名内部类的前提:必须继承或者实现一个外部类或者接口
public static void main(String[] args) {
//创建内部类并使用
Out out = new Out();
out.method();
//引用外部类中的内部类
In1 in = out.new In1();
in.show1();
//匿名内部类作为参数
parseIn parseIn =new parseIn();
show(parseIn);
}
public static void show(parseIn parseIn) { //匿名内部类可以作为参数
parseIn.show1();
parseIn.show2();
}
}
class parseIn implements In{
@Override
public void show1() {
System.out.println("Show1 Of Way3");
}
@Override
public void show2() {
System.out.println("Show2 Of Way3");
}
}
interface In{
abstract void show1();
abstract void show2();
}
class Out{
class In1{
void show1() {
System.out.println("Show1 Of In1");
}
}
void method() {
new In() {
@Override
public void show1() {
// TODO Auto-generated method stub
System.out.println("Show1 Of Way1");
}
@Override
public void show2() {
// TODO Auto-generated method stub
System.out.println("Show2 Of Way1");
}
}.show1();
In in = new In(){
@Override
public void show1() {
// TODO Auto-generated method stub
System.out.println("Show1 Of Way2");
}
@Override
public void show2() {
// TODO Auto-generated method stub
System.out.println("Show2 Of Way2");
}
}; //这里有个分号,
in.show2();
}
}
异常Exception
异常:运行时期发生的不正常情况,将问题封装成了对象
Exception vs Error:
Exception是java程序运行中可预料的异常情况,咱们可以获取到这种异常,并且对这种异常进行业务外的处理。
Error是java程序运行中不可预料的异常情况,这种异常发生以后,会直接导致JVM不可处理或者不可恢复的情况。所以这种异常不可能抓取到,比如OutOfMemoryError、NoClassDefFoundError等。
特点:可抛出(throws throw)
使用throw抛出异常:程序在throw语句后立即终止
格式:throw ThrowableInstance
使用throws抛出异常:
格式:返回类型 方法名() throws 异常类型1,异常类型2…{ … }
public class ThrowDemo {
public static void main(String[] args) {
int number = 0;
Scanner in=new Scanner(System.in);
String str = in.nextLine();
//Throw的使用
/*System.out.println("使用Throw");
try {
number =Integer.parseInt(str);
System.out.println("无异常");
} catch (Exception e) {
throw new ArrayIndexOutOfBoundsException("数组越界");
//System.out.println("非法数字");
}
System.out.println("输入数字:"+number);*/
//Throws的使用
System.out.println("使用Throws");
testThrows(str);
}
public static void testThrows(String string) {
try {
createThrows(string);
} catch (Exception e) {
System.out.println("来自createThrows方法的异常");
}
}
public static void createThrows(String string) throws Exception {
int number = 0;
number =Integer.parseInt(string);
System.out.println("输入数字:"+number);
}
}
结果:
//输入数字
1
使用Throw
无异常
输入数字:1
1
使用Throws
输入数字:1
//输入非数字
l
使用Throw
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 数组越界
at com.yyxx.day11.ThrowDemo.main(ThrowDemo.java:18)
l
使用Throws
来自createThrows方法的异常
finally关键字
- 不管是否发生异常,最终都能执行,用throw或者throws都一样
public class FinallyDemo {
public static void main(String[] args) {
int number = 0;
Scanner in = new Scanner(System.in);
int temp = in.nextInt();
try {
number = 12/temp;
System.out.println("get number:"+number);
} catch (Exception e) {
System.out.println("除零出错");
e.printStackTrace();//作用:打印出错信息
} finally {
System.out.println("最终执行");
}
}
}
结果
//输入数字1
1
get number:12
最终执行
//输入数字0
0
除零出错
java.lang.ArithmeticException: / by zero
最终执行
at com.yyxx.day11.FinallyDemo.main(FinallyDemo.java:12)
- finally块中的代码在return之前被执行,但是不能通过重新赋值来改变return的返回值
public class FinallyDemo {
public static void main(String[] args) {
System.out.print(Fi());
}
public static int Fi() {
int number = 0;
Scanner in = new Scanner(System.in);
int temp = in.nextInt();
try {
number = 12/temp;
return number;
} catch (Exception e) {
System.out.println("除零出错");
return 24;
} finally {
System.out.println("最终执行");
number = 36;
}
}
}
结果
//输入0
0
除零出错
最终执行
24
//输入1
1
最终执行
12
getMessage:返回Throwable对象的详细消息字符串
printStackTrace:将Throwable对象及其追踪输出至标准错误流
自定义异常类:比如抛出某些中文的异常提示信息
格式:
public class MyException extends Exception {
public My Exception () {
super();
}
public MyException ( String msg ) {
super ( msg) ;
}
public MyException ( Throwable cause ) {
super(cause);
}
}