Java学习笔记2

第二部分-面向对象高级

一.static

1.用static修饰叫做静态变量,静态方法。

2.随着类的加载而加载,静态变量只会加载一次。static存放在堆中的一个静态区域。

3.通过 类.static 的方式去调用静态方法。

静态方法不可以调用非静态结构。根据产生时间来理解会简单很多。

4.static修饰的方法内根本没有this和super之说。那是针对对象的。

5.方法内操作的变量是静态变量时,建议为静态方法。

二.单例模式

1.在类的内部创建对象。

对比两种模式(特点、优缺点) 特点:

饿汉式:“立即加载”,随着类的加载,当前的唯一实例就创建了 懒汉式:"延迟加载",在需要使用的时候,进行创建。

优缺点:

饿汉式:(优点)写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。 (缺点)内存中占用时间较长。 懒汉式:(缺点)线程不安全 (放到多线程章节时解决)(优点)在需要的时候进行创建,节省内存空间。

 public class BankTest {
     public static void main(String[] args) {
 //        Bank bank1 = new Bank();
 //        Bank bank2 = new Bank();
 ​
         Bank bank1 = Bank.getInstance();
         Bank bank2 = Bank.getInstance();
 ​
         System.out.println(bank1 == bank2);
 ​
     }
 }
 ​
 //饿汉式
 class Bank{
 ​
     //1. 类的构造器私有化
     private Bank(){
 ​
     }
 ​
     //2. 在类的内部创建当前类的实例
     //4. 此属性也必须声明为static的
     private static Bank instance = new Bank();
 ​
     //3. 使用getXxx()方法获取当前类的实例,必须声明为static的
     public static Bank getInstance(){
         return instance;
     }
 }

三.代码块

1.用来格式{}

2.只能使用static进行修饰

3.具体使用:静态代码块与非静态代码块。

 public class BlockTest {
     public static void main(String[] args) {
         System.out.println(Person.info);//先静态代码块,再静态属性
         Person p1=new Person();//先非静态代码块,再构造器
         System.out.println("------------");
         Person p2=new Person();//创建一次实例就会执行一次非静态代码块
         p1.eat();
         p1.play();
 ​
     }
 }
 class Person{
      String name="李四";
      int id=3445;
      public Person(){
          System.out.println("构造器的测试。");
      }
      public  void eat(){
          System.out.println("吃饭");
      }
      public  void play(){
          System.out.println("玩乐");
      }
      static String info ="信息";
     {
         id=98;
         info="信息1";
         System.out.println("非静态代码块测试"+id);
     }
 ​
     static{
 ​
         System.out.println("静态代码块测试");
     }
 ​
     //先静态代码块,再静态属性,再非静态代码块,最后是非静态的方法和属性
 }
 RESULT:
 静态代码块测试
 信息
 吃饭
 非静态代码块测试98
 构造器的测试。
 ------------
 吃饭
 非静态代码块测试98
 构造器的测试。
 吃饭
 玩乐

先类后对象。先静态后实例。先父类后子类。先代码块后构造器。(非静态代码块也要早于构造器)

四.final

1.final可以修饰类,方法,属性。

2.final修饰类表示类不能被继承,修饰方法表示方法不能被重写。

final修饰变量则就变成了常量。

有点道理:员工要注重发展长处,保持竞争力。而管理层就要注意短板,减少犯错。一个是要冲,一个是要稳。不同阶段有不同重要的事。

3.final与static结合为全局常量。

五.抽象类

1.抽象类不能实例化,即不能创建对象。但存在构造器。

2.抽象类可以没有抽象方法。抽象方法的功能是确定的,但没有方法体。

3.抽象修饰方法和类

 public  class AbstractTest {
     public static void main(String[] args) {
        Student8 s8=new Student8();
       // Person8 p8 =new Person8();不能实例化对象。
         
         
     }
 }
 abstract class   Person8{
     
     public abstract  void play();
     public abstract void eat();//抽象方法,没有方法体
 }
 class Student8 extends Person8{
     @Override
     public void eat() {
         System.out.println("学生会吃");
     }
 ​
     @Override
     public void play() {
         System.out.println("学生会玩");
     }//子类要将父类的抽象方法进行重写,不然就会被认定为含有父类的抽象方法而报错
 }

大国博弈,倒霉的肯定是小国。是这样的,布局向来也是要拿小棋去打开局面。去博弈。”

谈谈理解;抽象类及抽象方法还是有存在必要的。抽象方法所在的类为抽象类。比如求几何图形面积,求法虽然不同,但都是求面积,所以可以让子类重写抽象方法实行具体步骤。

进一步发现抽象其实是和多态紧密结合的。因为抽象不能创建对象,所以要用子类去创建对象。

4.模板方法设计模式

当功能的一部分确定时,而一部分是不确定的。将不确定的部分暴露出去,让子类去实现。

六.接口

1.接口基本知识

1.就是一套规范。

2.定义接口的关键字:interface

3.声明属性时:必须使用public static final(可以省略)就是说将为全局常量。

声明方法时:jdk8之前声明抽象方法,修饰为public abstract。

4.接口与类的关系:实现,implement。class A extends SuperA implement B,C

5.一个类可以实现多个接口。

6.接口与接口关系:可以多继承。

7.接口的多态.格式为:”接口 变量=new 实现类“。

 public class InterfaceTest {
 ​
     public static void main(String[] args) {
         System.out.println(Flyable.MAX_NUM);
         Flyable p1=new Plane();//   接口的多态.格式为:”接口 变量=new 实现类“。
         //p1.attrack;
         p1.fly();
         Plane p2=new Plane();
         p2.attrack();
         p2.fly();
 ​
     }
 }
 interface Flyable{
    public static final  int MAX_NUM=9;//属性可以省略public static final
    int MIN_SPEED=3000;
    void fly();
 ​
 }
 interface Attract{
        void attrack();
 }
 abstract class pullet implements Attract{
     @Override
     public void attrack() {
         System.out.println("子弹具有攻击性");
     }
 }
 class Plane implements Flyable,Attract{
     @Override
     public void fly() {
         System.out.println("飞机会飞");
     }
 ​
     @Override
     public void attrack() {
         System.out.println("具有攻击性");
     }
 }

2.接口例题

 package chapter9.exer2;
 /*
 有点意思,思考还是有趣的,不至于无聊到睡着
  */
 ​
 public class USBTest {
 ​
     public static void main(String[] args) {
         computer c1=new computer();
         //1 接口实现类的对象
         Printer p1=new Printer();
         c1.test99(p1);
         //2 接口实现类的匿名对象
         c1.test99(new campus());
         //3 接口匿名实现类的对象
         // 本来USB是一个接口,不能创建对象,因为有抽象方法。但是它相当于给自己进行了重写
         USB usb1=new USB() {
             @Override
             public void start() {
 ​
             }
 ​
             @Override
             public void finish() {
 ​
             }
         };
         c1.test99(usb1);
         //4.接口匿名实现类的匿名对象
         c1.test99(new USB() {
             @Override
             public void start() {
 ​
             }
 ​
             @Override
             public void finish() {
 ​
             }
         });
     }
 }
 interface USB{
     public static final int id =9;
     public abstract void start();
     public abstract  void finish();
 }
 class computer{
     public void  test99(USB usb){
         usb.start();
         System.out.println("数据开始传输");
         usb.finish();
         System.out.println("数据传输完成");
     }
 }
 class Printer implements USB{
     @Override
     public void start() {
         System.out.println("打字机开始工作");
     }
 ​
     @Override
     public void finish() {
         System.out.println("打字机结束工作");
     }
 }
 class campus implements USB{
     public void start(){
         System.out.println("照相机开始工作");
     }
 ​
     @Override
     public void finish() {
         System.out.println("照相机结束工作");
     }
 }

关于instanceof:本质上是看左边是否是右边的实例。

instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类所创建对象时,返回true;否则,返回false。

像这样是接口也是可以的。

 if(vehicles[i] instanceof IPower){
     ((IPower) vehicles[i]).power();
 }

3.接口在jdk8以后的新特性

1.接口中可以使用静态方法,但只能被接口来调用不能使用其实现类来调用。

2.接口中声明的默认方法可以被实现类使用,那如果实现类对默认方法进行了重写,自然使用的是重写过后的。

3.类可以实现多个接口,但如果接口定义了同名同参数的方法,则实现类会报错。接口冲突。

4.子类继承了父类并实现了接口,父类和接口声明了同名同参数的方法,则子类优先类中的方法。

5.如何在子类(或实现类)中调用父类或接口中被重写的方法。

  super.method4(); //调用父类中的
 ​
  method3();//调用自己类中的方法
 ​
  CompareA.super.method3(); //调用接口CompareA中的默认方法
  CompareB.super.method3(); //调用接口CompareB中的默认方法
 ​

七.内部类

---类的第五个内容

1.内部类的分类:成员内部类(又有静态与非静态之分)和局部内部类

成员内部类:直接声明在外部类的里面。 > 使用static修饰的:静态的成员内部类 > 不使用static修饰的:非静态的成员内部类

  局部内部类:声明在方法内、构造器内、代码块内的内部类
     > 匿名的局部内部类
     > 非匿名的局部内部类

2.内部类这节要讲的知识:

成员内部类的理解 如何创建成员内部类的实例 如何在成员内部类中调用外部类的结构

局部内部类的基本使用

例题1

package chapter9.exer6;

public class OuterClass {
 public static void main(String[] args) {
    Person.Dog dog=new Person.Dog();
    dog.eat();
    //因为是内部类,所以还是要明确外部
    //创建了内部类的一个对象。因为是静态的,所以不需要创建person对象
    Person p1=new Person();
    Person.Cat cat=p1.new Cat();
    //这个是非静态的,所以比上面的多一点,要先创建person对象。
    cat.eat();
    cat.show("黑鸟");
    cat.show1();

 }

}
class Person {
 public void eat(){
     System.out.println("人吃饭");
 }
 int age=34;
  String name="黄鹂";
  class Cat{
      String name="白鸟";
   public void eat(){

       System.out.println("鸟吃食物");
   }
   public void show(String name){
       System.out.println("age = "+age);
       System.out.println("name = "+this.name);//本类中的name
       System.out.println("name = "+name);//形参中的name
       System.out.println("name = "+Person.this.name);//外部类中的name
   }
   public void show1(){
       Person.this.eat();//调外部类的方法
       eat();//调自己的方法

      }
 }
 static class Dog{
      public void eat(){
          System.out.println("狗吃");
      }
 }
}

例题2

package chapter9.exer6;

public class OuterClassTest1 {
    public static void main(String[] args) {
        //SubObject subObject=new SubObject();
        //subObject.test();//1
        //new SubObject().test();//2
        //4 接口匿名实现类的匿名对象
        new Object() {
            public void test() {
                System.out.println("test0");
            }
        }.test();

        //传统写法。先创建对象,再调用方法
        C c1 = new C();
        c1.testc();
        //相当于把自己当作子类,然后重写了一遍方法,
        new C() {
            public void testc() {
                System.out.println("test3");
            }
        }.testc();
    }
}
class SubObject extends Object{
    public void test (){
        System.out.println("test1");
    }
}


class C{
    public void testc(){
        System.out.println("test2");
    }
}

八.枚举

1.类的对象是有限而且固定,推荐使用枚举。

2.自写枚举类

package chapter9.exer7;

public class EnumTest {
    public static void main(String[] args) {
        System.out.println(Season.SPRING);

    }
}
class Season{
    //
    private final String seasonName;
    private final String seasonDesc;
    //2.将构造器私有化,使其无法创建对象
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //3.获取特征,不希望被更改
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }
    public static final Season SPRING=new Season("春天","如坐春风");
    public static final Season summer=new Season("夏天","荷叶田田");
    public static final Season automn=new Season("秋天","秋风怒号");
    public static final Season winter=new Season("冬天","白雪皑皑");

    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

3.枚举关键字默认父类是java.lang.Enum

4.String toString(): 默认返回的是常量名(对象名),可以继续手动重写该方法! (关注)static 枚举类型[] values():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法 (关注)static 枚举类型 valueOf(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。 String name():得到当前枚举常量的名称。建议优先使用toString()。 int ordinal():返回当前枚举常量的次序号,默认从0开始

5.情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。

情况2:让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现的方法。

九.注解

1.几个基本注解

@override 修饰方法,表示方法要进行重写。

@SuppressWarnings("unused") int num =29;表示未使用

@Deprecated : 表示修饰的方法或类已经过时。

2.自定义注解

3.元注解:用来修饰注解的注解

@Target 用来描述注解的适用范围。

@Retention 用于描述注解的生命周期。

3.J-unit单元测试

要求:所在的类必须是public,非抽象的,包含唯一空参的构造器。

所在的方法必须是public,非抽象的,非静态的,void无返回值,()参数的。

十.包装类

问题引入:基本数据类型的优势在于效率高,然而有很多场景无法使用基本数据类型。比如equals(object obj)形参很多时候只能使用引用数据类型。所以引入了包装类。

1.基本数据类型定义了相应的包装类:int-->Integer char -->Character.其余首字母大写即可。

2.int num=10;Integer obj=new Integer(10);

3.将基本数据类型转化为包装类

int i1=10;
Integer i12=new Integer(i1);//方式1
System.out.println(i12);

Integer integer = Integer.valueOf(i1);//方式2,推荐使用
System.out.println(integer);

4.将包装类转化为基本数据类型

Integer integer1 = Integer.valueOf(23);
int i9=integer1.intValue();//转回去了
System.out.println(i9+4);结果为27

5.初始化值不一样,因为数据类型不一样

public void test3(){
    System.out.println(new Account().integer);//表示null
    System.out.println(new Account().i);//表示0
}
class Account{
    int i;
    Integer integer;

}

6.自动拆箱与自动装箱

public void test4(){
    int i1 =34;
    Integer integer=i1;//自动装箱 
    System.out.println(integer.toString());
    
    int i2=integer;//自动拆箱
    System.out.println(i2+4);
    
}

7.string类型与基本数据类型之间的转换。

//基本数据类型到String类型方式一
 int i=4;
 String str1=String.valueOf(i);
 System.out.println(str1);
//方式二
 int i1=5;
 String str2=i1+" ";
 System.out.println(str2);

 //Sting类型到基本数据类型
 String str3="45";
 int i4=4+Integer.parseInt(str3);
 System.out.println(i4);
Integer m=2;
Integer n=2;
  System.out.println(m==n);//true,

Integer x=128;
Integer y=128;
  System.out.println(x==y);//false,
//Integer和Byde在-128到127范围共用了一片空间,所以在这其中数值相等就是true,
  // 超过范围则要另外造对象,那么地址自然就不一样了。

十一.idea中的一些快捷键

ctrl +o:重写父类方法

ctrl +i :重写接口方法

CTRL+alt+left/right:返回上一次访问或下一次访问

ctrl +f :查找指定结构

ctrl+r :查找与替换

ctrl+shift+f:全项目搜索文本

ctrl +alt+l : 格式化代码

ctrl+/ :单行注释

ctrl+shift+/:多行注释

第1组:通用型

复制代码-copy ctrl + c 粘贴-paste ctrl + v 剪切-cut ctrl + x 撤销-undo ctrl + z 反撤销-redo ctrl + shift + z 保存-save all ctrl + s 全选-select all ctrl + a

第2组:提高编写速度(上)

智能提示-edit alt + enter 提示代码模板-insert live template ctrl+j 使用xx块环绕-surround with ... ctrl+alt+t 调出生成getter/setter/构造器等结构-generate ... alt+insert 自动生成返回值变量-introduce variable ... ctrl+alt+v 复制指定行的代码-duplicate line or selection ctrl+d 删除指定行的代码-delete line ctrl+y 切换到下一行代码空位-start new line shift + enter 切换到上一行代码空位-start new line before current ctrl +alt+ enter 向上移动代码-move statement up ctrl+shift+↑ 向下移动代码-move statement down ctrl+shift+↓ 向上移动一行-move line up alt+shift+↑ 向下移动一行-move line down alt+shift+↓ 方法的形参列表提醒-parameter info ctrl+p

第3组:提高编写速度(下)

批量修改指定的变量名、方法名、类名等-rename shift+f6 抽取代码重构方法-extract method ... ctrl+alt+m 重写父类的方法-override methods ... ctrl+o 实现接口的方法-implements methods ... ctrl+i 选中的结构的大小写的切换-toggle case ctrl+shift+u 批量导包-optimize imports ctrl+alt+o

第4组:类结构、查找和查看源码

如何查看源码-go to class... ctrl + 选中指定的结构 或 ctrl+n 显示当前类结构,支持搜索指定的方法、属性等-file structure ctrl+f12 退回到前一个编辑的页面-back ctrl+alt+← 进入到下一个编辑的页面-forward ctrl+alt+→ 打开的类文件之间切换-select previous/next tab alt+←/→ 光标选中指定的类,查看继承树结构-Type Hierarchy ctrl+h 查看方法文档-quick documentation ctrl+q 类的UML关系图-show uml popup ctrl+alt+u 定位某行-go to line/column ctrl+g 回溯变量或方法的来源-go to implementation(s) ctrl+alt+b 折叠方法实现-collapse all ctrl+shift+ - 展开方法实现-expand all ctrl+shift+ +

第5组:查找、替换与关闭

查找指定的结构 ctrl+f 查找与替换-replace ctrl+r 直接定位到当前行的首位-move caret to line start home 直接定位到当前行的末位 -move caret to line end end 全项目搜索文本-find in path ... ctrl+shift+f

第6组:调整格式

格式化代码-reformat code ctrl+alt+l 使用单行注释-comment with line comment ctrl + / 使用/取消多行注释-comment with block comment ctrl + shift + / 选中数行,整体往后移动-tab tab 选中数行,整体往前移动-prev tab shift + tab

关于调试:

1.普通断点:

2.方法断点:

3.属性断点:属性值发生改变的地方停留

4.条件断点:对于循环等等可以用这个

5.强制结束:发现了问题想要退出,不想再执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值