9.0 快速学习Java
9.1 快速学习Java
类的成员四:代码块(初始化块)
-
作用:用来初始化类、对象
-
代码块若有修饰符,只能是static
static代码块,随类加载而执行,且只执行一次;
非static代码块,随对象创建而加载,每创建一次执行一次;可以在创建对象时对对象属性进行初始化。
类的成员五:内部类
类A的声明,在另一个类B中。这样,A是内部类,B是外部类。
- 内部类按在类中声明的位置,分为 成员内部类 /局部内部类
成员内部类(静态、非静态)
- 作为外部类的成员在:1.调用外部类的结构;2.可以被static修饰;3.可以被4种权限修饰
- 作为一个类:1.类中可以定义属性、方法、构造器;2.可以被final修饰,表示不能被继承;3.可以被abstract修饰,表示抽象类
局部内部类
在代码块、方法、构造器中定义的类。
内部类的实例化
//Person类中定义了静态Brain类,在测试时创建Brain实例
Person.Brain brain = new Person.Brain();
//Person类中定义了**非静态**Brain类,在测试时创建Brain实例
Person p = new Person();
Person.brain b = p.new Brain();
成员内部类调用外部结构
//Person类中有一个内部类,内部类中的一个方法play
public void play(String name){
this.name = name;//name是方法的形参 this.name是内部类的属性
this.name = Person.this.name;//Person.this.name是外部类的属性
}
抽象类与抽象方法
类的设计保证父类和子类共享特征,将父类设计的非常抽象(我的理解,相当于把一类事物概括了,规定必须包含的特性,然后让继承的子类来根据自身特点修改具体内容)。
- 抽象方法的声明格式:public abstract void talk();
- 含抽象方法的类必须是抽象类;
- 抽象类是用来继承的,不能实例化;子类必须重写父类的抽象方法,如果没有全部重写抽象方法,则该子类还是抽象类;
- 不能用abstract修饰变量、代码块、构造器;
- 不能用abstract修饰private方法、static方法(JDK 7以后可以)、final方法、final类。
OPP特征一:封装与隐藏
程序设计的追求“高内聚,低耦合”
通过将数据声明为私有的(private),再提供公共的(public)方法:getXxx()和setXxx()实现对该属性的操作。以实现下述目的:
1.隐藏一个类中不需要对外提供的实现细节;
2.使用者只能通过事先定制好的方法来访问数据,可以方便地加入逻辑控制,限制对属性的不合理操作;
3.便于修改,增强代码的可维护性。
OPP特征二:继承性
子类(派生类),父类(基类或超类)。子类继承了父类,就继承了父类的方法和属性。
语法:class Subclass extends Superclass{…}
-
子类不能直接访问父类中私有的成员变量和方法。
-
Java中只支持单继承和多层继承,不支持多重继承。(子类只有一个直接父类)
方法的重写
子类对父类中继承来的方法进行改造。
要求:
1.子类重写的方法必须和父类被重写的方法同名、同参数列表;
2.子类重写方法的返回值类型不能大于父类该方法的返回值类型;
3.子类重写方法的访问权限不能小于父类的该方法(不能重写父类的private方法);
4.子类重写的方法抛出的异常不能大于父类的该方法;
5.必须同时声明为非static的。如果都是static的,则是类的方法,子类无法覆盖。
OPP特征三:多态性
对象的多态性:父类的引用指向子类的对象子类可以认为是特殊的父类。
Java引用变量有两个类型:编译时类型和运行时类型。简称:编译时,看左边;运行时,看右边
子类对象可以赋值给父类变量,但是编译时是只能调用父类属性与变量,不能调用子类特有的方法和属性;运行时,如果调用的方法,子类已重写了,则运行子类重写的方法,如果没有重写,则依旧运行父类自己的方法。
多态的用途,我的理解是,父类与子类或有实现关系的两类,把其中部分的方法又抽离出来使用,同时想实现各个类对抽离出来的方法都能有各自的反应。
instanceof: 例 x instanceof A检验x是否是类A的对象或子类。x所属类和A类必须是子父类关系,否则编译出错;如果x所属类是A类的父类,则返回false;如果x所属类是A类的子类,则返回true。
访问权限修饰符
接口(interface)
接口(interface)是抽象方法和常量值定义的集合。
- 接口的主要用途就是被实现类实现(面向接口编程)
- 与继承关系类似,接口与实现类之间存在多态性
- 接口和类是并列关系,或可理解为一种特殊的类
接口的特点:
- 用interface来定义
- 所有成员变量都默认是public static final修饰的
- 所有方法都默认是由public abstract修饰的
- 没有构造器
- 采用多继承机制,且接口可以继承其他接口
接口定义格式:
public interface Runner{
int ID = 1; //等同于public static final int ID = 1;
void start(); //等同于public abstract void start();
}
//Java中,先写extends,后写implements
JDK 8 接口以后支持静态方法和默认方法
public interface F{
int x = 0;
default void help(){//默认方法
System.out.println("Mom");
}
public static void help2(){//静态方法
System.out.println("static method.");
}
}
public interface S{
int x = 1;
default void help(){
System.out.println("Wife");
}
}
class Man implements F,S{
@Override
public void help(){
System.out.println("I will...");
F.super.help();//如果想用F中的默认方法
S.super.help();//如果想用S中的默认方法
System.out.println(F.x);//x是static变量,直接用F.来调用。如果是父类中没有static修饰的话,则用super.来调用
}
}
实现类同时实现的两个接口定义了同名的默认方法,会发生接口冲突。解决:实现类必须覆盖接口中的同名同参数的方法来解决;
实现类继承了一个父类和实现了一个接口,父类和接口中有同名同参的非抽象方法,则遵守:类优先原则
对象类型转换(Casting)
基本数据类型转换
-
自动类型转换:小的数据类型自动转换成大的数据类型
-
强制类型转换:大数据类型强制转换成小的数据类型
如float f = (float)12.0; int a = (int)1200L;
Java对象强制类型转换(造型)
-
子类到父类的类型转换可以自动进行
-
无继承关系的引用类型转换是非法的
-
父类到子类的类型转换通过造型(强制类型转换)实现,转换前先使用instanceof测试类型
-
通常,在父类的引用指向子类的对象时,需要强制类型转换。
例如,Student继承于Person,有对象 Person p = new Student();此时,p instanceof Student,是true,但是,p不能调用Student特有的方法和属性。通过Student ps = (Student)p;可以将p强制转换Student类型给ps。
Object类
Object类是所有Java类的根父类
-
==操作符 Vs equals方法
==:1.基本类型判断值是否相等;2.引用类型比较地址是否相同;3.==比较时两边数据类型必须兼容,否则编译出错。
- char ch = 65;System.out.println(65 == ch);//居然是true! A == ch 也是true
equals方法:1.基本数据类型判断值是否相等;2.对没有重写equals方法的,比较地址是否相同;3.重写了equals方法,按重写的判断。例如,File、String、Date以及包装类,重写了。比较的是类型及内容。
toString()方法
- 返回值是String类型,返回类名和它的引用地址。
- String类型与其他数据类型连接操作时,自动调用toString()方法;基本数据类型是调用了对应包装类的toString()方法。
- String类重写了toString,返回字符串的值
基本数据类型对应的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
- 特殊的:int和char
- Byte、Short、Integer、Long、Float、Double的父类是Number
装箱与拆箱
-
基本数据类型包装成包装类的实例 ——装箱
1.先定义变量:int i=500; Integer t = Integer.valueOf(i);
2.传入字符串:Integer t = Integer.valueOf(“500”);
-
获得包装类对象中包装的基本类型变量——拆箱
boolean b = bObj.booleanValue();
boolean b = bObj.valueOf(bObj);
PS :JDK1.5之后支持自动装拆箱。
-
字符串转换成基本数据类型
float f = Float.parseFloat(“12.1”);//12.1后加上f也可以
float f = Float.valueOf(“12.1f”);
-
基本数据类型转换成字符串
方式1:String fstr = 2.34 +"";
方式2:String fstr = String.valueOf(2.34f);
方式3:String foster = Float.toString(2.34f);
设计模式
单例(Singleton)设计模式
在整个软件系统中,某个类只存在一个对象实例。
饿汉式
class Singleton(){
//1.私有化构造器(使外部不能new对象)
private Singleton(){
}
//2.内部类提供一个当前类的实例(外部不能new对象,只能内部new然后提供给外部)
//4.因为提供的对象是本类的唯一实例,所以需要static
private static Singleton single = new Singleton();
//3.提供公共的静态的方法,返回当前类的对象(因为不能外部创建对象,只能用类方法来调用,所以要声明成static的)。
public static Singleton getInstance(){
return single;
}
}
懒汉式
//此演示有线程安全问题
class Singleton(){
//1.私有化构造器(使外部不能new对象)
private Singleton(){
}
//2.内部类提供一个当前类的实例(外部不能new对象,只能内部new然后提供给外部),这里没有初始化。
//4.因为提供的对象是本类的唯一实例,所以需要static
private static Singleton single;
//3.提供公共的静态的方法,返回当前类的对象(因为不能外部创建对象,只能用类方法来调用,所以要声明成static的)。
public static Singleton getInstance(){
if(single == null){
single = new Singleton();
}
return single;
}
}
//此演示避免来线程安全问题
class Singleton{
private static Singleton singleton = null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null){
syschronized(Single.class){ //两个是否为null的判断:外层是为了后续如果线程已经有实例,就可以不进入同步等待,直接返回实例;内层是为了如果首次多个线程判断为null然后单个进入,其他等待,没有里面的null判断的话,会造很多实例
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
模板方法设计模式(TemplateMethod)[多态、抽象类的应用]
在软件开发中,实现一个算法时,整体步骤很固定、通用,这些步骤在父类中写好了,但是某些部分易变,易变部分可以抽象出来,供不同子类实现。
abstract class Template{
long totalTime = 0l;
public final void getTime(){
long start = System.currentTimeMillis();
code();//易变部分,随code内容不同,整个getTime得到的时间不同
long end = System.currentTimeMillis();
totalTime = end - start;
}
public abstract void code();
}
//这里是for循环代码,代入测试运行时间
class ForCode extends Template {
public void code(){
for(int i = 0;i < 1000; i++){
System.out.println(i);
}
}
}
代理模式(Proxy)[接口的应用]
//接口
interface Network{
public void browse();
}
//被代理类
class RealServer implements Network{
@Override
public void browse(){
System.out.println("真实服务器上网浏览信息");
}
}
//代理类
class ProxyServer implements Network{
private Network network;
//构造器将network初始化。这里传入的实际是RealServer类的一个对象,用Nerwork类的对象去承接,体现了多态性。
public ProxyServer(Network network){
this network = network;
}
public void browse(){
check();
network.browse();//这里的network实际是指向RealServer的
}
public void check(){
System.out.println("安全检查.");
}
}
public class ProxyDemo{
public static void main(String[] args){
ProxyServer net = new ProxyServer(new RealServer());
net.browse();
}
}
其他
main方法
main(String[] args) 给main函数传入参数,先跑一下,生成字节码文件。run as ->Run configuration…->选择要传入的字节码文件->Arguments 填写参数,多个参数间用空格隔开