一、类变量、静态变量static
static访问方式:
public class VisitStatic {
public static void main(String[] args) {
//方法一:
//类名.类变量名
//说明:类变量是随着类的加载而创建,所以即使没有创建对象实例也可以访问
System.out.println(A.name);
//方法二:
A a = new A();
//通过对象名.类变量名
System.out.println("a.name=" + a.name);
}
}
class A {
//类变量
//类变量的访问,必须遵守 相关的访问权限.
public static String name = "韩顺平教育";
//普通属性/普通成员变量/非静态属性/非静态成员变量/实例变量
private int num = 10;
}
二、静态方法,类方法static
public static void hi() {
//类方法中不允许使用和对象有关的关键字,
//比如 this 和 super。普通方法(成员方法)可以。
System.out.println(this.n1);(报错)
}
静态方法(类方法)只能访问 静态方法或静态变量。
普通成员方法,既可以访问 非静态成员,也可以访问静态成
三、static课堂练习
答案:9 10 11
因为:count++ 所以先输出后++; 第一次 new count()方法,先输出9后,++则等于10。
第二次虽然也是new,但是是一个static方法,所以new出来的也是count=10。
四、main方法
五、代码块
作用:
(1) 下面的三个构造器都有相同的语句
(2) 这样代码看起来比较冗余
(3) 这时我们可以把相同的语句,放入到一个代码块中,即可
(4) 这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
(5) 代码块调用的顺序优先于构造器.
public class CodeBlock01 {
public static void main(String[] args) {
Movie movie = new Movie("你好,李焕英");
System.out.println("===============");
Movie movie2 = new Movie("唐探 3", 100, "陈思诚");
}
}
class Movie {
private String name;
private double price;
private String director;
{
System.out.println("电影屏幕打开...");
System.out.println("广告开始...");
System.out.println("电影正是开始...");
};
public Movie(String name) {
System.out.println("Movie(String name) 被调用...");
this.name = name;
}
public Movie(String name, double price, String director) {
System.out.println("Movie(String name, double price, String director) 被调用...");
this.name = name;
this.price = price;
this.director = director;
}
}
输出结果:
六、代码块的注意事项
七、单例设计模式
什么是单例:
单例模式应用实例:
以下代码不是单例模式,因为单例模式只能有一个实例对象。(只能有一个女朋友)
public class SingleTon01 {
public static void main(String[] args) {
GirlFriend xh = new GirlFriend("小红");
GirlFriend xb = new GirlFriend("小白");
}
}
//有一个类, GirlFriend
//只能有一个女朋友
class GirlFriend {
private String name;
public GirlFriend(String name) {
this.name = name;
}
}
修改为:单例模式-饿汉式
public class SingleTon01 {
public static void main(String[] args) {
//通过方法可以获取对象
GirlFriend instance = GirlFriend.getInstance();
System.out.println(instance);
}
}
//有一个类, GirlFriend
//只能有一个女朋友
class GirlFriend {
private String name;
//为了能够在静态方法中,返回 gf 对象,需要将其修饰为 static
//[单例模式-饿汉式]缺点:对象还没有创建就应该存在了。项目通常是重量級的對象, 饿汉式可能造成创建了对象,但是沒有使用,使得资源浪费
private static GirlFriend gf = new GirlFriend("小红红");
/*
*如何保障我们只能创建一个 GirlFriend 对象
*步骤[单例模式-饿汉式]
* 1. 将构造器私有化
* 2. 在类的内部直接创建对象(该对象是 static)
* 3. 提供一个公共的 static 方法,返回 gf 对象
*/
private GirlFriend(String name) {
this.name = name;
}
public static GirlFriend getInstance() {
return gf;
}
@Override
public String toString() {
return "GirlFriend [name=" + name + "]";
}
}
懒汉式:
public class SingleTon02 {
public static void main(String[] args) {
Cat instance = Cat.getInstance();
System.out.println(instance);
//再次调用 getInstance
Cat instance2 = Cat.getInstance();
System.out.println(instance2);
System.out.println(instance == instance2);// T
}
}
//希望在程序进行过程中,只能创建一个 Cat 對象
//使用单例模式
class Cat {
private String name;
private static Cat cat; // 默认是 null
/*
*步骤
* 1.仍然将造器私有化
* 2.定义一个 static 静态属性对象
* 3.提供一个 public 的 static 方法,可以返回一个Cat 对象
* 4.懒汉式:只有當用戶使用 getInstance 時,才返回 cat 对象, 后面再次调用时候,会返回上次创建的cat对象,
* 从而保证了单例
*/
private Cat(String name) {
this.name = name;
}
public static Cat getInstance() {
if (cat == null) { // 如果话沒有创建 cat 對象
cat = new Cat("小可爱");
}
return cat;
}
@Override
public String toString() {
return "Cat{" + "name='" + name + '\'' + '}';
}
}
运行结果:
饿汉式 VS 懒汉式
个人总结:
饿汉式中只要GirlFriend被调用则,不管调用哪个函数或者属性 比如:调用GirlFriend中的public static int a = 1;的情况下
private static GirlFriend gf = new GirlFriend(“小红红”);一定会被执行,则“小红有可能就在不需要的情况下就会被创建。”
而懒汉式则应用到了
if (cat == null) { cat = new Cat(“小可爱…”); }
需要经过判断才会被执行
八、final关键字
一般情况下final和static一起使用效率更高,不会导致类加载。
public class A {
public static void main(String[] args) {
System.out.println(AA.num);
}
}
class AA{
public static int num = 999;
static {
System.out.println("AA静态代码块被执行...");
}
}
输出结果:
static的代码块会被默认执行. . .
加上final后:
class AA{
public final static int num = 999;
static {
System.out.println("AA静态代码块被执行...");
}
}
final修饰的类或者属性被放在了常量池中
final练习://下面的代码是否有误,为什么?
public int addOne(final int x) {
++x; //错误,原因是不能修改 final x 的值
return x + 1; //这里是可以,因为没有改变x的值
}
九、抽象类的介绍
抽象类细节
细节1:
public static void main(String[] args) {
new AA(); // 报错!!!
}
abstract class AA{
}
练习题:
十、模板模式——抽象类
//抽象类-模板设计模式
abstract class Template {
// 抽象方法
public abstract void job();
// 实现方法,调用 job 方法
public void calculateTime() {
//得到开始的时间
long start = System.currentTimeMillis();
// 动态绑定机制
job();
//得的结束的时间
long end = System.currentTimeMillis();
System.out.println("任务执行时间 : " + (end - start));
}
}
// AA 类
class AA extends Template {
/*
* 计算任务
* 1+....+ 800000
* 实现 Template 的抽象方法 job
*/
@Override
public void job() {
long num = 0;
for (long i = 1; i <= 800000; i++) {
num += i;
}
}
}
// BB 类
class BB extends Template {
// 这里也去,重写了 Template 的 job 方法
public void job() {
long num = 0;
for (long i = 1; i <= 80000; i++) {
num *= i;
}
}
}
public class TestTemplate {
public static void main(String[] args) {
//子类调用父类方法。
AA aa = new AA();
aa.calculateTime(); // 这里还是需要有良好的 OOP 基础,对多态
BB bb = new BB();
bb.calculateTime();
}
}
十一、接口
接口和抽象类里的方法 一样都不需要写具体的方法体。其实接口中的方法可以看似成抽象方法,只不过在接口中的方法abstrac关键字可以省略。
默认方法需要在方法名前加关键字:default。且default仅仅只能使用在接口中
接口的细节
细节6:
interface A{
int n = 1; //实际上就等于 public static final int n = 1;
}
十二、接口 VS 继承
继承
小结: 当子类继承了父类,就自动的拥有父类的功能
如果子类需要扩展功能,可以通过实现接口的方式扩展.
可以理解 实现接口 是对 java 单继承机制的一种补充
十三、接口多态特征
//Usb接口
interface Usb{
void start();
void stop();
}
//手机
class Phone implements Usb {
@Override
public void start() {
System.out.println("手机连接成功开始工作...");
}
@Override
public void stop() {
System.out.println("手机断开成功结束工作...");
}
}
//照相机
class Camera implements Usb {
@Override
public void start() {
System.out.println("相机连接成功开始工作...");
}
@Override
public void stop() {
System.out.println("相机断开成功结束工作...");
}
}
//主机——电脑
class Computer {
public void work(Usb usb) {
usb.start();
usb.stop();
}
}
public class TestInterface {
public static void main(String[] args) {
Phone phone = new Phone();
Camera camera = new Camera();
Computer computer = new Computer();
//将 相机 连接到主机电脑...
computer.work(camera);
//将 手机 连接到主机电脑...
computer.work(phone);
}
}
十四、接口多态传递
//通过
BB bb = new CC();
AA aa = new CC();
}
}
interface AA {
void getAA();
}
interface BB extends AA{}
class CC implements BB {
@Override //必须重写
public void getAA() {
// TODO Auto-generated method stub
}
}
类的五大成员:属性、方法、构造器、代码块、内部类
十五、内部类
内部类一共有种:
15.1 局部 内部类
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.m1();
}
class Outer02 { // 外部类
private int n1 = 100;
private void m2() {
System.out.println("Outer02 m2(私有方法)");
}
public void m1() { //方法
/*
* 局部内部类是定义在外部类的局部位置,通常在方法中
* 作用域 : 仅仅在定义它的方法或代码块中。例如:内部类Inner02()只能在m1()方法体内使用
*/
class Inner02{
private int n1 = 999;
//可以直接访问外部类的所有成员,包含私有的 属性 或 方法
public void f1() {
m2();
//如果外部类和局部内部类的成员重名时
System.out.println("内部类的属性: "+n1);
System.out.println("外部类的属性: "+Outer02.this.n1);
}
}
//外部类在方法中,可以创建 Inner02 对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
15.2 匿名 内部类
public static void main(String[] args) {
Outer03 out = new Outer03();
out.method();
}
}
interface IA{
public void cry();
}
class Outer03 { // 外部类
public void method() {
/*
*基于接口的匿名内部类
*老韩解读
* 1.需求: 想使用 IA 接口,并创建对象
* 2.传统方式,是写一个类,实现该接口,并创建对象
* 3.老韩需求是 Tiger/Dog 类只是使用一次,后面再不使用
* 4. 可以使用匿名内部类来简化开发
* 5. tiger 的编译类型 ? IA
* 6. tiger 的运行类型 ? 就是匿名内部
* 其实底层 会分配 匿名内部类一个类名 Outer03$1
* jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址返回给 tiger
* 匿名内部类使用一次,就不能再使用(这里指的是方法体中的内容,不是指tiger对象,tiger对象可以使用多次)
*/
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎在叫唤...");
}
};
tiger.cry();
}
}