类
语法格式
修饰符 class 类名{
属性声明;
方法声明;
}
//修饰符public:类可以被任意访问,类的正文要用{}括起来
属性声明
修饰符 类型 属性名[ = 初值];
//修饰符 public 该属性可以类外的方法访问
//private 该属性只能在类中访问
- 成员变量
- 实例变量(不以
static修饰) - 类变量(
static修饰,通过类名.属性名直接使用)
- 实例变量(不以
- 局部变量
- 形参
- 方法局部变量
- 代码块局部变量
可变个数参数
//使用数组方式
//无参数,也要填[]或null
public void printInfo(String[] args){
for(int i= 0; i< args.length; i++)
System.out.println(args[i]);
}
//使用Java特有...方式
//使用方法与数组方式相同,传递参数直接用逗号隔开,不用数组形式
//无参数可不填
//这种方式如果多个形参,...一定要在最后的参数上
public void printInfo(String... args){
for(int i= 0; i< args.length; i++)
System.out.println(args[i]);
}
访问修饰符
| 修饰符 | 类内部 | 同一个包 | 子类 | 任何地方 |
|---|---|---|---|---|
private | YES | |||
| 缺省 | YES | YES | ||
protected | YES | YES | YES | |
public | YES | YES | YES | YES |
构造方法
public class Test{
public Test(){//构造函数前的修饰符与类名前的修饰符相同
//不写构造函数,默认会有,写了则会使用自己写的构造函数
}
public Test(String a){
//不同的参数的同名构造函数可以形成重载
}
}
关键字——super
super可用于访问父类中定义的属性super可用于调用父类中定义的成员方法super可用于在子类构造方法中调用父类的构造方法- 注意
- 尤其当子父类出现同名成员时,可以用
super进行区分 super的追溯不仅限于父类super和this的用法很像,this代表本类对象的引用,super代表父类的内存空间的标识- 在父类只有有参构造函数可以使用的时候,子类必须显式的构建一个构造函数来调用父类的有参构造,并且调用父类构造函数方法要写在第一行
- 尤其当子父类出现同名成员时,可以用
this和super的区别
| 区别点 | this | super |
|---|---|---|
| 访问属性 | 访问本类中的属性,如果本类没有此属性则从父类中继续查找 | 访问父类的属性 |
| 调用方法 | 访问本类中的方法 | 直接访问父类的方法 |
| 调用构造函数 | 调用本类的构造函数,必须放在构造函数的首行 | 调用父类构造函数,必须在子类构造函数首行 |
| 特殊 | 表示当前对象 | 无此概念 |
关键字——static
- 使用范围
- 在Java类中,可用
static修饰属性、方法、代码块、内部类
- 在Java类中,可用
- 被修饰后的成员具备以下特点
- 随着类的加载而加载
- 优先于对象存在
- 修饰的成员,被所有对象共享
- 访问权限允许时,可不创建对象,直接被类调用
初始化块
//注释为执行顺序
public class Test{
//1 初始化变量默认值
String name;
//3
public Test(){
this.name = "123";
System.out.pirntln("构造函数代码被执行");
}
//2
{
System.out.pirntln("初始化块代码被执行");
}
//0
static{
//只能使用静态static修饰的属性或方法,实际开发中用来初始化静态属性
//不管被实例化几次,都只执行一次
}
}
非静态代码块
没有static修饰的代码块
- 可以有输出语句。
- 可以对类的属性声明进行初始化操作。
- 可以调用静态和非静态的变量或方法。
- 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
- 每次创建对象的时候,都会执行一次。且先于构造器执行
静态代码块
用static修饰的代码块
- 可以有输出语句。
- 可以对类的属性声明进行初始化操作。
- 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
- 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
- 静态代码块的执行要先于非静态代码块。
- 静态代码块只执行一次
用处
public class Test{
public static void main(String[] args){
Person p = new Person(){
//匿名内部类 匿名子类
//Person类中的name属性已经初始化为张三,如何修改为李四
{
super.name = "李四";
}
}
}
}
静态导入包
//可以直接使用random()来调用
import static java.lang.Math.random;
关键字——final
-
final标记的类不能被继承。提高安全性,提高程序可读性。String类、System类、StringBuffer类 -
final标记的方法不能被子类重写。Object类中的getClass()方法 -
final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只被赋值一次final double PI = 3.14;final static double Pi =3.14;用final static修饰即为全局常量
抽象类
- 用
abstract关键字来修饰一个类时,这个类叫做抽象类 - 用
abstract来修饰一个方法时,该方法叫做抽象方法。 抽象方法:只有方法的声明,没有方法的实现。以分号结束:abstract int abstractMethod(int a); - 含有抽象方法的类必须被声明为抽象类。
- 抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。
- 不能用
abstract修饰属性、私有方法、构造器、静态方法、final的方法。
内部类
在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。
- 内部类一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。
- 内部类的名字不能与包含它的类名相同;
- 内部类可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员。
- 分类:
- 成员内部类(
static成员内部类和非static成员内部类) - 局部内部类(不谈修饰符)、匿名内部类
- 成员内部类(
public class Test{
int i;
public int z;
private int k;
class A{
int i;
public void setTest(){
Test.this.i=1;
Test.this.z=2;
Test.this.k=3;
}
public void setMyself(){
this.i=4;
}
}
public void setInfo(){
new A().setTest();
}
public void showInfo(){
System.out.println(this.i);
System.out.println(this.z);
System.out.println(this.k);
}
public static void main(String[] args){
Test t = new Test();
t.setInfo();
t.showInfo();
}
}
特性
- 可以声明为
final的 - 和外部类不同,
Inner class可声明为private或protected Inner class可以声明为static的,但此时就不能再使用外层类的非static的成员变量Inner class作为类:- 可以声明为
abstract类,因此可以被其它的内部类继承
- 可以声明为
- 【注意】非
static的内部类中的成员不能声明为static的,只有在外部类或static的内部类中才可声明static成员。
作用
解决Java不能多重继承的问题。
public class Test{
public static void main(String[] args){
A a = new A();
a.method2();
a.method3();
}
}
//A中想要使用BC中的方法,但是Java不支持多重继承
//所以用内部类继承,再重写
class A{
public void method2(){
new InnerB().method2();
}
public void method3(){
new InnerC().method3();
}
private class InnerB extends B{
@Override
public void method2(){
System.out.println("这是重写后的method2");
}
}
private class InnerC extends C{
@Override
public void method3(){
System.out.println("这是重写后的method3");
}
}
}
class B{
public void method2(){
}
}
class C{
public void method3(){
}
}
JVM
内存模型
实例化原理
包
关键字——package
package语句作为java源文件的第一条语句,指明该文件中定义的类所在的包。- 若缺省该语句,则指定为无名包
- 格式为
package 顶层包名.子包名 - 通常包名小写单词,类名首字母大写
- 一般利用公司域名倒置作为包名比如,com.baidu.www
关键字——import
- 引用别的包
- 同一个包下面,不用引用
import 包名.类名- 可以用
*表示所有
instanceof
对象 instanceof 类名;
//返回值为布尔值
//判断是否为该类所实例化的对象
JavaBean
JavaBean是一种Java语言写成的可重用组件JavaBean是指符合以下标准的类- 类是公共的
- 有一个无参的公共的构造函数
- 有属性,且有对应的
get,set方法
继承
修饰符 sonClass extends superClass{
}
- 继承的出现提高了代码的复用性
- 继承的出现让类与类之间产生了关系,提供了多态的前提
- 不要仅为了获取其他类中的某个功能而去继承
- Java只能单继承,一个子类只有一个父类
组合
在面向对象编程原则中,组合>继承。
//这是继承
class A extends B{
...
}
//这是组合,可以使用B的全部功能,优先使用这种方法
class A{
Public B b;
}
方法重写
@Override
public void showInfo(){
}
- 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型
- 重写方法不能用比被重写方法更严格的修饰符
- 重写和被重写的方法必须同时为
static或者为非static - 子类方法抛出的异常不能大于父类被重写方法的异常
多态
- 两种体现
- 方法的重载(
overload)和重写(overwrite) - 对象的多态性,可以直接应用在抽象类和接口上
- 方法的重载(
- Java引用变量有两种类型,编译时类型和运行时类型。前者由声明变量时使用的类型决定,后者由实际赋值的类型决定
- 若编译时类型和运行时类型不一致,就会出现多态(
Polymorphism)
- 若编译时类型和运行时类型不一致,就会出现多态(
向上转型
//Student类是Person类的子类
Person p = new Person();
Person e = new Student();
//不能调用Student中新增的属性或方法
小结
- 前提
- 需要存在继承或者实现关系
- 需要覆盖操作
- 成员方法
- 编译时,要查看引用变量所属的类是否存在所调用的方法
- 运行时,调用实际对象所属的类中的重写方法
- 成员变量
- 不具备多态性,只看引用变量所属的类
Object类
Object类是所有Java类的跟父类,基类- 如果在类的声明中没有
extends,那么默认指定继承于Object类 - 在方法中,参数需要一个对象,但是不知道是什么类,可以用
Object类作为形参
对象类型转换
-
对Java对象的强制类型转换称为造型
-
从子类到父类的类型转换可以自动进行
Son son = new Son(); Father faher = son; -
从父类到子类的类型转换需要造型(强制类型转换)实现
Father father = new Father(); Son son = (Son)father; -
无继承关系的引用类型间的转换是非法的
-
==和equal
==- 在两个基本类型之间比较,只要两个变量相等,即为
true - 在两个引用类型之间比较,需要两个引用指向同一个对象时,才返回
true - 用
==进行比较时,符号两边的数据类型必须兼容(可自动转换的基本类型除外),否则编译出错
- 在两个基本类型之间比较,只要两个变量相等,即为
equal()- 所有的类都继承于
Object类,所以所有的类都有equal()方法 - 该方法和
==相同,但只能比较两个引用类型 - 特例:对
File、String、Date及包装类(wrapperClass)来说,是比较类型和内容而不考虑引用的是否是同一个对象,原因是在类中重写了equal()方法 - PS:比较字符串用
equal方法而不是==
- 所有的类都继承于
包装类
| 基本数据类型 | 包装类 |
|---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
装箱
-
通过包装类的构造函数实现
int i = 500; Integer t = new Integer(i); Integer t1 = 500;//自动装箱 -
还可以通过字符串参数构造包装类对象
Float f = new Float("4.56");//字符串内容一定要符合类型,不然NumberFormatException
拆箱
-
调用包装类的
xxxValue()方法boolean b = bObj.booleanValue(); boolean b = bObj;//自动拆箱 -
JDK1.5后,支持自动装箱,自动拆箱,但类型必须匹配
字符串转换基本数据类型
-
通过包装类的构造器实现
int i = new Integer("111"); -
通过包装类的静态方法实现
Float f = Float.parseFloat("12.1");
基本类型转换成字符串
-
调用字符串重载的
valueOf()方法String fstr = String.valueOf(2.34f); -
更直接
String intStr = 5 + "";
设计模式
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索。
单例设计模式
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造方法的访问权限设置为private,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。
使用单例模式解决什么问题?一般都是new对象太费劲,或者频频的new新的对象没有必要。
//饿汉式单例模式
public class Single{
//私有的构造,构造方法私有化,调用这个类的人就不能直接使用new来创建对象
private Single(){
}
//私有的single类型的类变量
private static Single single =new Single();
public static Single getInstance(){
reutrn single;
}
}
//懒汉式
public class Single1{
private Single1(){
}
public static Singgle1 single1 = null;
public static getInstance(){
if(single1 == null)
single1 = new Single1();
return single1;
}
}
模板设计模式
抽象类
工厂方法
接口
有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。接口(interface)是抽象方法和常量值的定义的集合。
从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
实现接口类:
class SubClass implements InterfaceA,InterfaceB{}
一个类可以实现多个接口,接口也可以继承其它接口。
接口的特点
- 用
interface来定义。 - 接口中的屏有成员变量都默认是由
public static final修饰的。 - 接口中的所有方法都默认是由
public abstract修饰的。 - 接口没有构造器。
- 接口采用多层继承机制。
public interface Runner{
int ID = 1;//默认添加了 public abstract final 修饰
void start();//默认添加了 public abstract 修饰
public void run();
void stop();
}
实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类。
接口的主要用途就是被实现类实现。(面向接口编程)
与继承关系类似,接口与实现类之间存在多态性定义刘ava类的语法格式:先写extends,后写implements
接口和抽象类
- 抽象类需要稳定的抽象,切忌随意更改
- 新增的常量和方法,通过接口来实现,而不是改造抽象类
- 抽象类实现接口,不用实现接口中的所有方法