java学习笔记7——面向对象
关键字:static




类变量

静态变量的内存解析:

相关代码:
public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值之后Chinese c1 = new Chinese();c1.name = "姚明";c1.age = 40;c1.nation = "China";Chinese c2 = new Chinese();c2.name = "刘翔";c2.age = 39;System.out.println(c1);System.out.println(c2);System.out.println(c1.nation); // ChinaSystem.out.println(c2.nation); // Chinac2.nation = "CHN";System.out.println(c1.nation); // CHNSystem.out.println(c2.nation); // CHN}
}
class Chinese { //中国人类//非静态变量、实例变量String name;int age;//静态变量、类变量/*** China* China* CHN* CHN*/static String nation = "中国";/*** China* null* China* CHN*/
// String nation;@Overridepublic String toString() {return "Chinese{" +"name='" + name + '\'' +", age=" + age +'}';}
}
类方法(class method)


案例1:
编写一个类实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额"、“利率"、“最小余额", 定义封装这些属性的方法,账号要自动生成。编写主类,使用银行账户类,输入、输出3个储户的上述信息。考虑:哪些属性可以设计成static属性x
相关代码:
AccountTest
public class AccountTest {public static void main(String[] args) {Account acct1 = new Account();System.out.println(acct1);Account acct2 = new Account("123456", 2000);System.out.println(acct2);Account.setInterestRate(0.0123);Account.setMinBalance(10);System.out.println("银行存款的利率为:" + Account.getInterestRate());System.out.println("银行存款的额度为:" + Account.getMinBalance());}
}
Account
public class Account {private int id; //账号private String password; //密码private double balance; //余额private static double interestRate; //利率private static double minBalance = 1.0; //最小余额private static int init = 1001; //用于自动生成id的基数public Account(){this.id = init;init++;password = "000000";}public Account(String password, double balance) {this.password = password;this.balance = balance;this.id = init;init++;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}public static double getInterestRate() {return interestRate;}public static void setInterestRate(double interestRate) {Account.interestRate = interestRate;}public static double getMinBalance() {return minBalance;}public static void setMinBalance(double minBalance) {Account.minBalance = minBalance;}@Overridepublic String toString() {return "Account{" +"id=" + id +", password='" + password + '\'' +", balance=" + balance +'}';}
}
面试题:
public class StaticTest {public static void main(String[] args) {Order order = null;//可以打印出来,静态并不依赖于对象,直接通过类调用即可order.hello(); //hello!System.out.println(order.count); //1}
}
class Order{public static int count = 1;public static void hello() {System.out.println("hello!");}
}
本章总结:
static关键字的使用1. static:静态的2.static 用来修饰的结构:属性、方法;代码块、内部类3.static修饰属性3.1 复习:变量的分类方式1:按照数据类型:基本数据类型、引用数据类型方式2:按照类中声明的位置成员变量:按照是否使用static修饰进行分类:使用static修饰的成员变量:静态变量、类变量不使用static修饰的成员变量:非静态变量、实例变量局部变量:方法内、方法形参、构造器内、构造器形参、代码块内等。3.2 静态变量:类中的属性使用static进行修饰。对比静态变量与实例变量:① 个数> 静态变量: 内存空间中只有一份,被类的多个对象所共享。> 实例变量: 类的每一个实例(或对象)都保存着一份实例变量。② 内存位置> 静态变量: jdk6及之前:存放在方法区。jdk7之后:存放在堆空间> 实例变量: 存放在堆空间的对象实体中③ 加载时机> 静态变量: 随着类的加载而加载,由于类只会加载一次,所以静态变量也只有一份。> 实例变量: 随着对象的创建而加载。每个对象拥有一份实例变量。④ 调用者> 静态变量: 可以被类直接调用,也可以使用对象调用。> 实例变量: 只能使用对象进行调用。⑤ 判断是否可以调用 ---> 从生命周期的角度解释类变量 实例变量类 yes no对象 yes yes⑥ 消亡时机> 静态变量: 随着类的卸载而消亡> 实例变量: 随着对象的消亡而消亡4.static修饰方法:(类方法、静态方法)> 随着类的加载而加载 > 可以通过"类.静态方法"的方式,直接调用静态方法 > 静态方法内可以调用静态的属性或静态的方法(属性和方法的前缀使用的是当前类,可以省略)不可以调用非静态的结构。(比如:属性、方法)类变量 实例变量类 yes no对象 yes yes > static修饰的方法内,不能使用this和super> 补充:在类的非静态方法中,可以调用当前类中的静态结构(属性、方法)或非静态结构(属性、方法)5.开发中,什么时候需要将属性声明为静态的?> 判断当前类的多个实例是否能共享此成员变量,且此成员变量的值是相同的。> 开发中,常将一些常量声明是静态的。比如:Math类中的PI什么时候需要将方法声明为静态的?> 方法内操作的变量如果都是静态变量(而非实例变量)的话,则此方法建议声明为静态方法> 开发中,常常将工具类中的方法,声明为静态方法。比如:Arrays类、Math类
单例 (Singleton)设计模式

单例模式和实现思路(如果我们要让类在一个虚拟机...):

单例(Singleton)设计模式-饿汉式

单例(Singleton)设计模式-懒汉式

单例模式的优点


总结:
1.设计模式概述: 设计模式是在大量的`实践中总结`和`理论化`之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索. 就像是经典的棋谱,不同的棋局,我们用不同的棋谱。"套路"经典的设计模式一共有23种。2.何为单例模式(Singleton): 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。3.如何实现单例模式(掌握): > 饿汉式> 懒汉式4.对比两种模式(特点、优缺点) 特点: > 饿汉式:“立即加载”,随着类的加载,当前的唯一实例就创建了 > 懒汉式:"延迟加载",在需要使用的时候,进行创建。优缺点: > 饿汉式:(优点)写法简单,由于内存中较早加载,使用更方便、更快。是线程安全的。(缺点)内存中占用时间较长。 > 懒汉式: (缺点)线程不安全 (放到多线程章节时解决)(优点)在需要的时候进行创建,节省内存空间。
实例代码:
//饿汉式
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); //true}
}
//饿汉式
class Bank {//1.类的构造器石私有化private Bank(){}//2.在类的内部创建当前类的实例//4.此属性也必须声明为static的private static Bank instance = new Bank();//3.使用getXXX()方法获取当前类的实例,必须声明为static的public static Bank getInstance(){return instance;}
}//懒汉式
public class GirlFriendTest {public static void main(String[] args) {GirlFriend test1 = GirlFriend.getInstance();GirlFriend test2 = GirlFriend.getInstance();System.out.println(test1 == test2); //true}
}
class GirlFriend {//1.类的构造器私有化private GirlFriend() {}//2.声明当前类的实例化//4.此属性也必须声明为static的private static GirlFriend instance = null;//3.通过getXXX()获取当前类的实例,如果未创建对象,则在方法内部进行创建public static GirlFriend getInstance(){if(instance == null){instance = new GirlFriend();}return instance;}
}
理解main方法的语法

方式2:使用main()的形参进行传值。 代码:
public class MainDemo {public static void main(String[] args) {for (int i = 0; i < args.length; i++) {System.out.println("hello:" + args[i]);}}
}
命令行的方式传值:在执行命令后空格 写上实参![]()
idea的传值方式
点击编辑配置:


执行结果:

总结:
main()方法的剖析
public static void main(string args[]){}1.理解1: 看做是一个普通的静态方法理解2: 看做是程序的入口,格式是固定的。2.与控制台交互
如何从键盘获取数据?
> 方式1:使用Scanner
> 方式2:使用main()的形参进行传值。命令行的方式传值 idea的传值方式
相关代码:
MainTest
public class MainTest {public static void main(String[] args) { //程序的入口String[] arr = new String[]{"AA", "BB", "CC"};Main.main(arr);}
}
class Main{public static void main(String[] args) { //看做是普通的静态方法System.out.println("Main的main()的调用");for(int i = 0; i < args.length; i++){System.out.println(args[i]);}/*** Main的main()的调用* AA* BB* CC*/}
}
类的成员之四:代码块



总结:
类的成员之四:代码块回顾:类中可以声明的结构:属性、方法、构造器;代码块(或初始化块)、内部类1.代码块(或初始化块)的作用: (即初始化类或对象的成员变量)用来初始化类或对象的信息2.代码块的修饰:只能使用static进行修饰。3.代码块的分类:静态代码块:使用static修饰非静态代码块:没有使用static修饰4.具体使用: 4.1 静态代码块:> 随着类的加载而执行> 由于类的加载只会执行一次,进而静态代码块的执行,也只会执行一次> 作用:用来初始化类的信息> 内部可以声明变量、调用属性或方法、编写输出语句等操作。> 静态代码块的执行要先于非静态代码块的执行> 如果声明有多个静态代码块,则按照声明的先后顺序执行> 静态代码块内部只能调用静态的结构(即静态的属性、方法),不能调用非静态的结构(即非静态的属性、方法) 4.2 非静态代码块:> 随着对象的创建而执行> 每创建当前类的一个实例,就会执行一次非静态代码块> 作用:用来初始化对象的信息> 内部可以声明变量、调用属性或方法、编写输出语句等操作。> 如果声明有多个非静态代码块,则按照声明的先后顺序执行>非静态代码块内部可以调用静态的结构(即静态的属性、方法),也可以调用非静态的结构(即非静态的属性、方法)
代码:
(1)声明User类 - 包含属性:userName(String类型),password(String类型),registrationTime(long类型),私有化- 包含get/set方法,其中registrationTime没有set方法- 包含无参构造,- 输出“新用户注册”,- registrationTime赋值为当前系统时间- userName就默认为当前系统时间值,- password默认为"123456"- 包含有参构造(String userName,String password)- 输出“新用户注册”,- registrationTime赋值为当前系统时间,- username和password由参数赋值- 包含public String getInfo()方法,返回:"用户名:xx,密码:xx,注册时间:xx"(2)编写测试类,测试类main方法的代码
UserTest
public class UserTest {public static void main(String[] args) {User u1 = new User();System.out.println(u1.getInfo());User u2 = new User("Tom","654321");System.out.println(u2.getInfo());System.out.println();User1 u3 = new User1();System.out.println(u3.getInfo());}
}User1
public class User1 {private String userName;private String password;private long registrationTime; //注册时间public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public long getRegistrationTime() {return registrationTime;}{System.out.println("新用户注册");registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)}//代码块的使用public User1(){
// System.out.println("新用户注册");
// registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)userName = System.currentTimeMillis() + "";password = "123456";}public User1(String userName, String password) {
// System.out.println("新用户注册");
// registrationTime = System.currentTimeMillis(); //获取系统当前时间(距离1970-1-1 00:00:00的毫秒数)this.userName = userName;this.password = password;}public String getInfo(){return "用户名:" + userName + ",密码:" + password + ",注册时间为:" + registrationTime;}
}
Field,属性赋值过程
总结:
可以给类的非静态的属性(即实例变量)赋值的位置有: ① 默认初始化 ② 显式初始化 或 ⑤ 代码块中初始化 ③ 构造器中初始化 ****************************** ④ 有了对象以后,通过"对象.属性"或"对象.方法"的方法进行赋值2.执行的先后顺序: ① - ②/⑤ - ③ - ④3.(超纲)关于字节码文件中的<init>的简单说明:(通过插件jclasslib bytecode viewer查看) > <init>方法在字节码文件中可以看到。每个<init>方法都对应着一个类的构造器。(类中声明了几个构造器就会有几个<init>) > 编写的代码中的构造器在编译以后就会以<init>方法的方式呈现 > <init>方法内部的代码包含了实例变量的显示赋值、代码块中的赋值和构造器中的代码。 > <init>方法用来初始化当前创建的对象的信息的。4.给实例变量赋值的位置很多,开发中如何选? > 显示赋值:比较适合于每个对象的属性值相同的场景 > 构造器中赋值:比较适合于每个对象的属性值不相同的场景
相关代码:
public class FieldTest {public static void main(String[] args) {Order o1 = new Order();System.out.println(o1.orderId); //1 ---> 2 ---> 3}
}
class Order {/*** 显式初始化 与 代码块中初始化 可以更换位置* 此时的执行结果是1* 反之执行结果是2* order类的加载有一个系的过程,在初始化之前orderId就已经被默认初始化了,并且默认为0,在后面才开始显示赋值或者代码块赋值*/
// {
// orderId = 2;
// }
// int orderId = 1;int orderId = 1;{orderId = 2;}//构造器会以init的方式呈现的字节码中//字节码暴露了我们加载的顺序public Order(){super();
// orderId = 3;}public Order(int orderId){this.orderId = orderId;}//对象调用eat方法之前,类中就已经存在了sleep和eat方法了,所以不会报错public void eat(){sleep();}public void sleep(){}
}
字节码文件:

两个构造函数,两个init

面试题1:
/*** static A* static B* I'm A Class* HelloA* I'm B Class* HelloB*/
class HelloA {public HelloA() {System.out.println("HelloA");}{System.out.println("I'm A Class");}static{System.out.println("static A");}
}
class HelloB extends HelloA {public HelloB() {System.out.println("HelloB");}{System.out.println("I'm B Class");}static {System.out.println("static B");}
}
public class Test01 {public static void main(String[] args) {new HelloB();}
}
面试题2:
public class Test02 {static int x, y,z;static {int x = 5;x--; //就近原则,操作的是新定义的x}static {x--;}public static void method(){y = z++ + ++z;}public static void main(String[] args) {System.out.println("x = " + x);z--; //-1method(); //-1 + 1 = 0 = y z: 1System.out.println("result:" + (z + y + ++z)); //1 + 0 + 2 = 3}
}
面试题3:
/*** Base* sub:100* sub* base:70*/
class Base {Base(){method(100);}{System.out.println("Base");}public void method(int i){System.out.println("base:" + i);}
}
class Sub extends Base {Sub(){super.method(70);}{System.out.println("sub");}public void method(int i){System.out.println("sub:" + i);}
}
public class Test03 {public static void main(String[] args) {Sub s = new Sub();}
}
关键字:final





总结:
final关键字的使用1.final的理解:最终的2.final可以用来修饰的结构:类、方法、变量3.具体说明:3.1 final修饰类:表示此类不能被继承。比如:String、stringBuffer、stringBuilder类 3.2 final修饰方法:表示此方法不能被重写比如:0bject类中的getClass() 3.3 final修饰变量:既可以修饰成员变量,也可以修饰局部变量。此时的"变量"其实就变成了"常量",意味着一旦赋值,就不可更改。3.3.1 final修饰成员变量:有哪些位置可以给成员变量赋值?> 显式赋值> 代码块中赋值> 构造器中赋值3.3.2 final修饰局部变量:一旦赋值就不能修改> 方法内声明的局部变量: 在调用局部变量前,一定需要赋值。而且一旦赋值,就不可更改> 方法的形参: 在调用此方法时,给形参进行赋值。而且一旦赋值,就不可更改4.final与static搭配: 修饰成员变量时,此成员变量称为:全局常量。 比如:Math的PI
相关代码:
public class FinalTest {public static void main(String[] args) {E e = new E();System.out.println(e.MIN_SCORE);//编译不通过
// e.MIN_SCORE = 1;E e1 = new E(10);
// e1.LEFT = 11; //不可更改}
}
class E {//成员变量final int MIN_SCORE = 0; //显式赋值final int MAX_SCORE;final int LEFT;
// final int RIGHT; //不赋值会报错{
// MIN_SCORE = 1;MAX_SCORE = 100; //代码块赋值}{
// MAX_SCORE = 1; //编译不通过}public E(){LEFT = 2;}public E(int left){LEFT = left;}//报错
// public void setRight(int right){
// RIGHT = right;
// }
}
class F {public void method(){final int num = 10;
// num++;//编译报错System.out.println(num);}public void method(final int num){
// num++; //编译报错System.out.println(num);}
}
final class A {}
//报错,不能被继承
//class B extends A {
//
//}
//class subString extends String {}
class C{public final void method(){}
}
class D extends C{//不能被重写
// public void method(){
//
// }
}
面试题:
题目1:排错
public class Something {public int addOne(final int x){return ++x; //会报错,x已被赋值了//return x+1;}
}题目2:排错
public class Something {public static void main(String[] args){Other o = new Other();new Something().addOne(o);}//这个地方final修饰的是o,如果o被重新赋值了的话就会报错//但是i是一个变量,他是用final修饰的public void addOne(final Other o){//o= new Other();o.i++;}
}class Other {public int i:
}
抽象类与抽象方法



选中这行按alt+enter键,选择实现方法(用于抽象子类重写父类的抽象方法)

弹出要实现的方法确定即可

案例:
Creature
public abstract class Creature { //生物类public abstract void breath(); //呼吸
}Person
public abstract class Person extends Creature { //抽象类String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public abstract void eat(); //抽象方法public abstract void sleep(); //抽象方法
}Student
public class Student extends Person {String school;public Student() {}public Student(String name, int age, String school) {super(name, age);this.school = school;}public void eat(){System.out.println("学生多吃有营养的食物");}public void sleep(){System.out.println("学生要保证充足的睡眠");}@Overridepublic void breath() {System.out.println("学生应该多呼吸新鲜空气");}
}Worker
//public abstract class Worker extends Person{
//
//}
public abstract class Worker extends Person{@Overridepublic void eat() {System.out.println("工人很辛苦,多吃");}
}AbstractTest
public class AbstractTest {public static void main(String[] args) {//编译不通过
// Person p1 = new Person();
// p1.eat();Student s1 = new Student();s1.eat();//抽象类不能实例化
// Worker w1 = new Worker();}
}AbstractTest1
public class AbstractTest1 {//编译不通过
// private abstract void method(){};
// public static abstract void method(){};
}
抽象类应用


多态的应用:模板方法设计模式(TemplateMethod)


总结:
抽象类与抽象方法1.案例引入
举例1:Geometric0bject-Circle-Rectangleabstract class Geometric0bject{//几何图形//求面积(只能考虑提供方法的声明,而没有办法提供方法体。所以,此方法适合声明为抽象方法)//求周长(只能考虑提供方法的声明,而没有办法提供方法体。所以,此方法适合声明为抽象方法)
}class Circle extends Geometric0bject {//求面积(必须重写(或实现)父类中的抽象方法)//求周长(必须重写(或实现)父类中的抽象方法)
}举例2:Account-SavingAccount-CheckAcount
class Account{double balance;//余额//取钱 (声明为抽象方法)//存钱 (声明为抽象方法)
}class SavingAccount extends Account{ //储蓄卡//取钱 (需要重写父类中的抽象方法)//存钱 (需要重写父类中的抽象方法)
}class CheckAccount extends Account{ //信用卡//取钱 (需要重写父类中的抽象方法)//存钱 (需要重写父类中的抽象方法)
}//......2.abstract的概念:抽象的3.abstract可以用来修饰:类、方法4.具体的使用:4.1 abstract修饰类:> 此类称为抽象类> 抽象类不能实例化。> 抽象类中是包含构造器的,因为子类对象实例化时,需要直接或间接的调用到父类的构造器。> 抽象类中可以没有抽象方法。反之,抽象方法所在的类,一定是抽象类,(因为需要确保这个方法不能被调用,而方法是需要通过对象来调用,这样干脆让类为抽象类,不能实例化)4.2 abstract修饰方法> 此方法即为抽象方法> 抽象方法只有方法的声明,没有方法体。> 抽象方法其功能是确定的(通过方法的声明即可确定),只是不知道如何具体实现(体现为没有方法体)> 子类必须重写父类中的所有的抽象方法之后,方可实例化。否则,此子类仍然是一个抽象类5.abstract不能使用的场景
5.1 abstract 不能修饰哪些结构?
属性、构造器、代码块等。5.2 abstract 不能与哪些关键字共用? (自洽)
不能用abstract修饰私有方法、静态方法、final的方法、final的类
> 私有方法不能重写
> 避免静态方法使用类进行调用
> final的方法不能被重写
> final修饰的类不能有子类
练习:
编写工资系统,实现不同类型员工(多态)的按月发放工资。如果当月出现某个 Employee对象的生日,则将该雇员的工资增加100元。实验说明: (1)定义一个Employee类,该类包含: private成员变量name,number,birthday,其中birthday 为MyDate类的对象;提供必要的构造器 abstract方法earnings(); toString()方法输出对象的name,number和birthday。(2)MyDate类包含: private成员变量year,month,day ;提供必要的构造器 toDateString()方法返回日期对应的字符串:xxxx年xx月xx日(3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处 理。该类包括:private成员变量monthlySalary; 提供必要的构造器; 实现父类的抽象方法earnings(),该方法返回monthlySalary值;toString()方法输 出员工类型信息及员工的name,number,birthday。比如:SalariedEmployee[name = '', number = '', birthday = ''](4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的 员工处理。该类包括: private成员变量wage和hour; 提供必要的构造器; 实现父类的抽象方法earnings(),该方法返回wage*hour值; toString()方法输出员工类型信息及员工的name,number,birthday。比如:HourlyEmployee[name = '', number = '', birthday = ''](5)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各 类雇员对象的引用。利用循环结构遍历数组元素,输出各个对象的类 型,name,number,birthday,以及该对象生日。当键盘输入本月月份值时,如果本 月是某个Employee对象的生日,还要输出增加工资信息。 提示: //定义People类型的数组People c1[]=new People[10]; //数组元素赋值 c1[0]=new People("John","0001",20); c1[1]=new People("Bob","0002",19); //若People有两个子类Student和Officer,则数组元素赋值时,可以使父类类型的数组元素指向子类。 c1[0]=new Student("John","0001",20,85.0); c1[1]=new Officer("Bob","0002",19,90.5);TemplateMethodTest public class TemplateMethodTest {public static void main(String[] args) {BankTemplateMethod btm = new DrawMonney();btm.process();BankTemplateMethod btm2 = new ManageMonney();btm2.process();} } abstract class BankTemplateMethod {//具体方法public void takeNumber(){System.out.println("排队取号");}public abstract void transact();public void evaluate(){System.out.println("反馈评分");}//模板方法,把基本操作组合到一起,子类一般不能重写public final void process(){this.takeNumber();this.transact(); //像个钩子,具体执行时,挂哪个类,就执行哪个子类的实现代码this.evaluate();} } class DrawMonney extends BankTemplateMethod {public void transact(){System.out.println("我要取款!!!");} } class ManageMonney extends BankTemplateMethod {public void transact(){System.out.println("我要理财!我这里有2000万美元!!");} }或练习 public class TemplateTest {public static void main(String[] args) {PrintPrimeNumber p = new PrintPrimeNumber();p.spendTime();} } abstract class Template {//计算某段代码的执行,需要花费的时间public void spendTime(){long start = System.currentTimeMillis();code();long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));}public abstract void code(); } class PrintPrimeNumber extends Template {public void code(){for(int i = 2; i <= 100000; i++){boolean isFlag = true;for(int j = 2; j <= Math.sqrt(i); j++){if(i % j == 0){isFlag = false;break;}}if(isFlag){System.out.println(i);}}} }
接口(interface)










相关代码:
public class InterfaceTest {public static void main(String[] args) {System.out.println(Flyable.MIN_SPEED);System.out.println(Flyable.MAX_SPEED);//编译报错
// Flyable.MAX_SPEED = 7800;Bullet b1 = new Bullet();b1.fly();b1.attack();//接口的多态性Flyable f1 = new Bullet();f1.fly(); //编译的时候是接口当中的方法,但是运行的时候是实现类当中的方法}
}
interface Flyable { //接口//全局常量public static final int MIN_SPEED = 0;// 可以省略public static finalint MAX_SPEED = 7900;//方法可以省略public abstract声明
// public abstract void fly();void fly();
}
interface Attackable { //接口public abstract void attack();
}
abstract class Plane implements Flyable,Attackable {}
class Bullet implements Flyable {public void fly() {System.out.println("让子弹飞一会儿");}public void attack(){System.out.println("子弹可以击穿身体");}
}
//测试接口的继承关系
interface AA {void method1();
}
interface BB{void method2();
}
interface CC extends AA,BB{ //接口可以多继承
}
class DD implements CC {public void method1(){}public void method2(){}
}
练习题:
设备连接

/*** 设备连接成功...* 打印机开始工作* 数据传输的细节操作...* 打印机结束工作* 设备连接成功...* 照相机开始工作* 数据传输的细节操作...* 照相机结束工作* 设备连接成功...* U盘开始工作* 数据传输的细节操作...* U盘开始结束工作* 设备连接成功...* 扫描仪开始工作* 数据传输的细节操作...* 扫描仪结束工作*/
public class USBTest {public static void main(String[] args) {//1.创建接口实现类的对象Computer computer = new Computer();Printer printer = new Printer();computer.transferDate(printer);//2.创建接口实现类的匿名对象computer.transferDate(new Camera());//3.创建接口匿名实现类的对象USB usb1 = new USB(){public void start(){System.out.println("U盘开始工作");}public void stop(){System.out.println("U盘开始结束工作");}};computer.transferDate(usb1);//4.创建接口匿名实现类的匿名对象computer.transferDate(new USB(){public void start(){System.out.println("扫描仪开始工作");}public void stop(){System.out.println("扫描仪结束工作");}});}
}
class Computer {public void transferDate(USB usb){System.out.println("设备连接成功...");usb.start();System.out.println("数据传输的细节操作...");usb.stop();}
}
class Camera implements USB {@Overridepublic void start() {System.out.println("照相机开始工作");}@Overridepublic void stop() {System.out.println("照相机结束工作");}
}
class Printer implements USB {@Overridepublic void start() {System.out.println("打印机开始工作");}@Overridepublic void stop() {System.out.println("打印机结束工作");}
}
interface USB {//声明常量//USB的长、宽、高...//方法public abstract void start();void stop();
}
练习2:
1、声明接口Eatable,包含抽象方法public abstract void eat(); 2、声明实现类中国人Chinese,重写抽象方法,打印用筷子吃饭 3、声明实现类美国人American,重写抽象方法,打印用刀叉吃饭 4、声明实现类印度人Indian,重写抽象方法,打印用手抓饭 5、声明测试类EatableTest,创建Eatable数组,存储各国人对象,并遍历数组,调用eat()方法
Chinese
public class Chinese implements Eatable {public void eat() {System.out.println("中国人使用筷子吃饭");}
}
American
public class American implements Eatable {@Overridepublic void eat() {System.out.println("美国人使用刀叉吃饭");}
}
Indian
public class Indian implements Eatable{@Overridepublic void eat() {System.out.println("印度人使用手抓饭");}
}public interface Eatable {void eat();
}EatableTest
public class EatableTest {public static void main(String[] args) {Eatable[] eatables = new Eatable[3];eatables[0] = new Chinese(); //多态性eatables[1] = new American();eatables[2] = new Indian();/*** 中国人使用筷子吃饭* 美国人使用刀叉吃饭* 印度人使用手抓饭*/for (int i = 0; i < eatables.length; i++) {eatables[i].eat();}}
}
练习题3:
定义一个接口用来实现两个对象的比较。interface CompareObject{//若返回值是0,代表相等;若为正数,代表当前对象大;负数代表当前对象小public int compareTo(Object o);
}
定义一个Circle类,声明radius属性,提供getter和setter方法定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。
在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo方法比较两个类的半径大小。拓展:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在ComparableRectangle类
中给出compareTo方法的实现,比较两个炬形的面积大小。
CompareObject
public interface CompareObject {//若返回值是 0,代表相等,若为正数,代表当前对象大;负数代表当前对象小public int compareTo(Object o);
}Circle
public class Circle {private double radius; //半径public Circle() {}public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}@Overridepublic String toString() {return "Circle{" +"radius=" + radius +'}';}
}ComparableCircle
public class ComparableCircle extends Circle implements CompareObject {public ComparableCircle() {}public ComparableCircle(double radius) {super(radius);}//根据对象半径的大小,比较对象的大小@Overridepublic int compareTo(Object o) {if(this == o) {return 0;}if(o instanceof ComparableCircle) {ComparableCircle c = (ComparableCircle)o;// 错误的
// return (int)(this.getRadius() - c.getRadius());//正确的写法1:
// if(this.getRadius() > c.getRadius()) {
// return 1;
// }else if(this.getRadius() < c.getRadius()){
// return -1;
// }else {
// return 0;
// }//正确的写法2:return Double.compare(this.getRadius(), c.getRadius());}else {return 2; //如果输入的类型不匹配,则返回2
// throw new RuntimeException("输入的类型不匹配");}}
}
InterfaceTest
public class InterfaceTest {public static void main(String[] args) {ComparableCircle c1 = new ComparableCircle(2.3);ComparableCircle c2 = new ComparableCircle(5.3);int compareValue = c1.compareTo(c2);if(compareValue > 0){System.out.println("c1对象大");}else if(compareValue < 0){System.out.println("c2对象大");}else{System.out.println("c1和c2一样大");}}
}
接口的应用:代理模式(Proxy)






总结:
接口的使用1.接口的理解:接口的本质是契约、标准、规范,就像我们的法律一样。制好后大家都要遵守2.定义接口的关键字:interface3.接口内部结构的说明:> 可以声明:属性:必须使用public static final修饰方法:jdk8之前:声明抽象方法,修饰为public abstractjdk8:声明静态方法、默认方法jdk9:声明私有方法> 不可以声明: 构造器、代码块等4.接口与类的关系:实现关系5.格式: class A extends SuperA implements B,C{}
A相较于SuperA来讲,叫做子类
A相较于B,C来讲,叫做实现类。6.满足此关系之后,说明:
> 类可以实现多个接口。
> 类针对于接口的多实现,一定程度上就弥补了类的单继承的局限性。
> 类必须将实现的接口中的所有的抽象方法都重写(或实现),方可实例化。否则,此实现类必须声明为抽象类。7.接口与接口的关系: 继承关系,且可以多继承8.接口的多态性: 接口名 变量名 = new 实现类对象;// 父类 变量名 = new 子类对象; 类的多态性
9.面试题:区分抽象类和接口
> 共性:都可以声明抽象方法都不能实例化
> 不同:① 抽象类一定有构造器。接口没有构造器② 类与类之间继承关系,类与接口之间是实现关系,接口与接口之间是多继承关系
相关代码 :
CompareA
public interface CompareA {//属性:声明为public static final//方法:jdk8之前,只能声明抽象方法//方法:jdk8中:静态方法public static void method1(){System.out.println("CompareA:北京");}//方法:jdk8中:默认方法
// public void method3(); //这种写法是抽象方法,不是抽象方法就需要抽象体public default void method2(){System.out.println("CompareA:上海");};public default void method3(){System.out.println("CompareA:广州");};public default void method4(){System.out.println("CompareA:深圳");};//jdk9新特性:定义私有方法private void method5(){System.out.println("我是接口中定义的私有方法");}
}
CompareB
public interface CompareB {public default void method3(){System.out.println("CompareB: 广州");}
}
SuperClass
public class SuperClass {public void method4() {System.out.println("SuperClass:深圳");}
}
SubClassTest
public class SubClassTest {public static void main(String[] args) {//知识点1:接口中声明的静态方法只能被接口来调用,不能使用期实现类进行调用CompareA.method1();
// SubClass.method1(); //编译不通过//默认方法涉及到造对象,重写之后调用的是重写之后的方法//知识点2:接口中声明的默认方法可以被类继承,实现类在没有重写此方法的情况下,默认调用接口中声明的//默认方法,如果实现类重写了此方法,则调用的是自己重写的方法SubClass s1 = new SubClass();s1.method2();//知识点3:类实现了两个接口,而两个接口中定义了同名同参数的默认方法,则实现类在没有重写此两个接口//默认方法的情况下,或报错,--->接口冲突//要求:此时实现类必须要重写接口中定义的同名同参数的方法s1.method3();//知识点4:子类(或实现类)继承了父类并实现了接口,父类和接口中声明了同名同参数的方法,(其中,接口中的方法//是默认方法)。默认情况下,子类(或实现类)在没有重写此方法的情况下,调用的是父类中的方法。---> 类优先原则/*** CompareA:北京* SubClass:上海* SubClass:广州* SuperClass:深圳 ---> SubClass:深圳(子类重写之后)*/s1.method4();}
}
SubClass
public class SubClass extends SuperClass implements CompareA, CompareB {@Overridepublic void method2() {System.out.println("SubClass:上海");}@Overridepublic void method3() {System.out.println("SubClass:广州");}public void method4() {System.out.println("SubClass:深圳");}public void method(){//知识点5:如何在子类(或实现类)中调用父类或接口中重写的方法method4(); //调用自己类中的方法super.method4();method3(); //调用自己类中的方法
// CompareA.method1(); //静态方法可以这样调用,不是静态的方法按照下面的方式调用CompareA.super.method3(); //调用接口CompareA中的默认方法CompareB.super.method3(); //调用接口CompareB中的默认方法}
}
类的成员之五:内部类

内部类生成的文件通过 $内部类名 来表示






代码示例:
public class OuterClassTest {public static void main(String[] args) {//1.创建Person的静态的成员内部类的实例Person.Dog dog = new Person.Dog();dog.eat();//2.创建Person的非静态的成员内部类的实例
// Person.Bird bird = new Person.Bird(); //报错Person p1 = new Person();Person.Bird bird = p1.new Bird(); //正确的bird.eat();bird.show("黄鹂");bird.show1();}
}
class Person { //外部类String name = "Tom";int age = 1;//静态的成员内部类static class Dog{public void eat() {System.out.println("狗吃骨头");}}//非静态的成员内部类class Bird{String name = "啄木鸟";public void eat(){System.out.println("鸟吃虫子");}public void show(String name){System.out.println("age = " + age); //age = 1 省略了Person.thisSystem.out.println("name = " + name); //name = 黄鹂System.out.println("name = " + this.name); //name = 啄木鸟System.out.println("name = " + Person.this.name); //name = Tom}public void show1(){eat(); //鸟吃虫子this.eat(); //鸟吃虫子Person.this.eat(); //人吃饭}}public void eat(){System.out.println("人吃饭");}public void method(){//局部内部类class innerClass1{}}public Person(){//局部内部类class innerClass1{}}{//局部内部类class innerClass1{}}
}
代码示例2:
public class OuterClassTest1 {//说明:局部内部类的使用public void method1(){//局部内部类class A{//可以声明属性、方法等}}//开发中的场景public Comparable getInstance(){//提供了实现了Comparable接口的类//方式1:提供了接口的实现类的对象
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
// }
// MyComparable m = new MyComparable();
// return m;//方式1:提供了接口的实现类的匿名对象
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
// }
// return new MyComparable();//方式2:提供了接口的匿名实现类的对象//后面的大括号表示实现类
// Comparable c = new Comparable() {
// @Override
// public int compareTo(Object o) {
// return 0;
// }
// };
// return c;//方式3:提供了接口的匿名实现类的匿名对象return new Comparable(){@Overridepublic int compareTo(Object o) {return 0;}};}
}
代码示例3:
public class OuterClassTest2 {public static void main(String[] args) {SubA a = new SubA();a.method();//举例1:提供了接口匿名实现类的对象A a1 = new A(){public void method() {System.out.println("匿名实现类重写的方法method()");}};a1.method();//举例2:提供了接口匿名实现类的匿名对象new A(){public void method() {System.out.println("匿名实现类重写的方法method()");}}.method();//举例3:SubB s1 = new SubB();s1.method1();//举例4:提供了继承于抽象类的匿名子类的对象B b = new B() {@Overridepublic void method1() {System.out.println("继承于抽象类的子类调用的方法");}};b.method1();System.out.println(b.getClass()); //class com.atguigu09.inner.OuterClassTest2$3System.out.println(b.getClass().getSuperclass()); //class com.atguigu09.inner.B//举例5:new B(){@Overridepublic void method1() {System.out.println("继承于抽象类的子类调用的方法1");}}.method1();//举例6:C c = new C();c.method2();//举例7:提供了一个继承于C的匿名子类的对象
// C c1 = new C(){};C c1 = new C(){public void method2() {System.out.println("SubC");}};c1.method2();
// System.out.println(c.getClass());//class com.atguigu09.inner.C
// System.out.println(c1.getClass().getSuperclass());//class com.atguigu09.inner.C}
}
interface A{public void method();
}
class SubA implements A{public void method(){System.out.println("SubA");}
}
abstract class B{public abstract void method1();
}
class SubB extends B{public void method1(){System.out.println("SubB");}
}
class C{public void method2(){System.out.println("C");}
}
练习1:
编写一个匿名内部类,它继承Object,并在匿名内部类中,声明一个方法public void test()打印尚硅谷。 请编写代码调用这个方法。
public class ObjectTest {public static void main(String[] args) {
// SubObject sub1 = new SubObject();
// sub1.test();//提供一个继承于Object的匿名子类的匿名对象new Object(){public void test(){System.out.println("尚硅谷");}}.test();}
}
class SubObject extends Object{public void test(){System.out.println("尚硅谷");}
}
native关键字的理解:

枚举类enum


单例模式当中有饿汉式与懒汉式
总结:
枚举类的使用 1.枚举类的理解:枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。 2.举例: - 星期:Monday(星期一)......Sunday(星期天) - 性别:Man(男)、Woman(女) - 月份:January(1月)......December(12月) - 季节:Spring(春节)......Winter(冬天) - 三原色:red(红色)、green(绿色)、blue(蓝色) - 支付方式:Cash(现金)、WechatPay(微信)、Alipay(支付宝)、BankCard(银行卡)、Creditcard(信用卡) - 就职状态:Busy(忙碌)、Free(空闲)、Vocation(休假)、Dimission(离职) - 订单状态:Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配货)、Delivered(已发货)、checked(已确认收货)、Return(退货)、Exchange(换货)、Cancel(取消) - 线程状态:创建、就绪、运行、阻塞、死亡3.开发中的建议: > 开发中,如果针对于某个类,其实例是确定个数的,则推荐将此类声明为枚举类 > 如果枚举类的实例只有一个,则可以看做是单例的实现方式。4.JDK5.0 之前如何自定义枚举类(了解) 见代码 5.JDK5.0中使用enum定义枚举类 见代码 6.Enum中的常用方法: 6.1 使用enum关键字定义的枚举类,默认其父类是java.lang.Enum类使用enum关键字定义的枚举类,不要再显示的定义其父类。否则报错 6.2 熟悉Enum类中常用的方法string toString():默认返回的是常量名(对象名),可以继续手动重写该方法!(关注)static 枚举类型[] valves():返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值,是一个静态方法(关注)static 枚举类型 value0f(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的"名字"。如不是,会有运行时异常:IllegalArgumentException。String name():得到当前枚举常量的名称。建议优先使用toString()。int ordinal():返回当前枚举常量的次序号,默认从0开始 7.枚举类实现接口的操作情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。情况2:让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现的方法。
相关代码1:
public class SeasonTest {public static void main(String[] args) {
// Season.AUTUMN = null; //报错System.out.println(Season.SPRING);System.out.println(Season.SUMMER.getSeasonName());System.out.println(Season.SUMMER.getSeasonDesc());}
}
//jdk5.0之前定义的枚举方式
class Season{//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//1.私有化类的构造器private Season(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}//4.创建当前类的实例,使用public static final修饰public static final Season SPRING = new Season("春天", "春暖花开");public static final Season SUMMER = new Season("夏天", "夏日炎炎");public static final Season AUTUMN = new Season("秋天", "秋高气爽");public static final Season WINTER = new Season("冬天", "白雪皑皑");@Overridepublic String toString() {return "Season{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}
相关代码2:
public class SeasonTest1 {public static void main(String[] args) {
// System.out.println(Season1.SPRING.getClass()); //class com.atguigu10._enum.Season1
// System.out.println(Season1.SPRING.getClass().getSuperclass()); //class java.lang.Enum
// System.out.println(Season1.SPRING.getClass().getSuperclass().getSuperclass()); //class java.lang.Object//测试方法//1.toString()System.out.println(Season1.SPRING); //SPRING(toString()重写之前)//2.name()System.out.println(Season1.SPRING.name()); //SPRING//3.values()Season1[] values = Season1.values();/*** Season1{seasonName='春天', seasonDesc='春暖花开'}* Season1{seasonName='夏天', seasonDesc='夏日炎炎'}* Season1{seasonName='秋天', seasonDesc='秋高气爽'}* Season1{seasonName='冬天', seasonDesc='白雪皑皑'}*/for(int i=0; i<values.length; i++){System.out.println(values[i]);}//4.valueOf(String objName):再返回当前枚举类中名称为objName的枚举对象//如果枚举类不存在objName名称的对象,则报错String objName = "WINTER";
// objName = "WINTER1"; //报错IllegalArgumentExceptionSeason1 season1 = Season1.valueOf(objName);System.out.println(season1);//5.ordinal()System.out.println(Season1.AUTUMN.ordinal()); //2//通过枚举类的对象调用重写后的接口中的方法Season1.AUTUMN.show();}
}
interface Info{void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season1 implements Info{//1.必须在枚举类的开头声明多个对象,对象之间使用,隔开SPRING("春天", "春暖花开"),SUMMER("夏天", "夏日炎炎"),AUTUMN("秋天", "秋高气爽"),WINTER("冬天", "白雪皑皑");//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//3.私有化类的构造器private Season1(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}@Overridepublic String toString() {return "Season1{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}@Overridepublic void show() {System.out.println("这是一个季节");}
}改进2
public class SeasonTest2 {public static void main(String[] args) {Season2[] values = Season2.values();for(int i = 0; i < values.length; i++){
// System.out.println(values[i]);values[i].show();}}
}
interface Info1{void show();
}
//jdk5.0中使用enum关键字定义枚举类
enum Season2 implements Info1{//1.必须在枚举类的开头声明多个对象,对象之间使用,隔开SPRING("春天", "春暖花开"){public void show(){System.out.println("春天在哪里?");}},SUMMER("夏天", "夏日炎炎"){public void show(){System.out.println("宁静的夏天");}},AUTUMN("秋天", "秋高气爽"){public void show(){System.out.println("秋意浓");}},WINTER("冬天", "白雪皑皑"){public void show(){System.out.println("大约在冬季");}};//2.声明当前类的对象的实例变量,使用private final修饰private final String seasonName; //季节的名称private final String seasonDesc; //季节的描述//3.私有化类的构造器private Season2(String seasonName, String seasonDesc){this.seasonName = seasonName;this.seasonDesc = seasonDesc;}//3.提供实例变量的get方法public String getSeasonName(){return seasonName;}public String getSeasonDesc(){return seasonDesc;}@Overridepublic String toString() {return "Season1{" +"seasonName='" + seasonName + '\'' +", seasonDesc='" + seasonDesc + '\'' +'}';}
}
就职状态代码:
Employee
public class Employee {private String name;private int age;private Status status;public Employee() {}public Employee(String name, int age, Status status) {this.name = name;this.age = age;this.status = status;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Status getStatus() {return status;}public void setStatus(Status status) {this.status = status;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", status=" + status +'}';}
}
枚举:
public enum Status {BUSY,FREE,VOCATION,DIMISSION;
}
EmployeeTest
public class EmployeeTest {public static void main(String[] args) {Employee e1 = new Employee("Tom", 21, Status.BUSY);System.out.println(e1); //Employee{name='Tom', age=21, status=BUSY}}
}
案例:使用枚举类实现单例模式
public class BnakTest1 {public static void main(String[] args) {
// Bank1.instance = null; //final可以用但不能修改System.out.println(GirlFriend.XIAL_LI); //XIAL_LI}
}
//jdk5.0之前的使用枚举类定义单例模式
class Bank1 {//饿汉式
// private Bank1(){}
// private static Bank1 instance = new Bank1();
// public static Bank1 getInstance(){
// return instance;
// }//枚举类没有通过方法调用,而是直接通过类来调用private Bank1(){}private static final Bank1 instance = new Bank1();
}
//jdk5.0使用enum关键字定义枚举类的方式定义单例模式
enum Bank2{CPB;
}
enum GirlFriend{
// public static final GirlFriend XIAL_LI = new GirlFriend(20); //之前写法XIAL_LI(20);private final int age;private GirlFriend(int age){this.age = age;}
}
案例:
案例拓展:颜色枚举类(使用enum声明) (1)声明颜色枚举类Color: - 声明final修饰的int类型的属性red,green,blue - 声明final修饰的String类型的属性description - 声明有参构造器Color(int red,int green,int blue,String description) - 创建7个常量对象:红、橙、黄、绿、青、蓝、紫, - 重写toString方法,例如:RED(255,0,0)->红色 (2)在测试类中,使用枚举类,获取绿色对象,并打印对象。 提示: - 7个常量对象的RGB值如下: 红:(255,0,0) 橙:(255,128,0) 黄:(255,255,0) 绿:(0,255,0) 青:(0,255,255) 蓝:(0,0,255) 紫:(128,0,255)7个常量对象名如下 RED, ORANGE,YELLOW, GREEN,CYAN, BLUE,PURPLEpublic class ColorTest {public static void main(String[] args) {System.out.println(Color.BLUE);} } enum Color {RED(255,0,0,"红色"),ORANGE(255,128,0,"橙色"),YELLOW(255,255,0,"黄色"),GREEN(0,255,0,"绿色"),CYAN(0,255,255,"青色"),BLUE(0,0,255,"蓝色"),PURPLE(128,0,255,"紫色");private final int red;private final int green;private final int blue;private final String description; //颜色的描述Color(int red, int green, int blue, String description) {this.red = red;this.green = green;this.blue = blue;this.description = description;}public int getRed() {return red;}public int getGreen() {return green;}public int getBlue() {return blue;}public String getDescription() {return description;}@Overridepublic String toString() { // return name()+ "(" + red + "," + green + "," + blue + ")" + "--->" + description;return super.toString()+ "(" + red + "," + green + "," + blue + ")" + "--->" + description;} }
annotation注解的使用








`@SuppressWarnings`:抑制编译器警告
移动到元素上,选择更多操作


结果如下: @SuppressWarnings("unused") int num = 10;

JUnit单元测试




怎么添加单元测试包,通过+号选择库(library)

务必选择编译

就可以为当前模块(module)添加单元测试(junit)
也可以通过选中当前@Test这个测试类,按住alt+enter回车键,在有网的情况下下载包
默认情况下,单元测试方法中使用Scanner失效。如何解决?
在单元测试里面如果没有做什么配置,在这个地方输入什么都无法显示


如果不想是只读的,输入的数值可以显示出来,在help里面选择编辑自定义虚拟机选项

在这个文件中将这一句话加上:-Deditable.java.test.console=true

之后在文件地方选择使缓存失效

点击重启,或者直接关闭idea,重新打开也可

此时再输入数值就可以正常显示了

结果显示:

如何将将单元测试设置成一个模板?


使用模板,在光标出输入需要输入的值

总结和相关代码:
JUnit单元测试的使用 1.需要导入的jar包: junit-4.12.jar hamcrest-core-1.3.jar 2.导入步骤 见课件 3.创建单元测试类,进行测试 见代码 4.(重点关注)要想能正确的编写单元测试方法,需要满足: - 所在的类必须是public的,非抽象的,包含唯一的无参构造器。 - @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。 5.默认情况下,单元测试方法中使用Scanner失效。如何解决?6.大家可以将单元测试设置成一个模板?public class JunitTest { //单元测试类public static void main(String[] args) {//静态方法调用非静态方法需要进行测试JunitTest test = new JunitTest();System.out.println(test.number);test.method();}int number = 10;@Testpublic void test1() { //单元测试方法System.out.println("Hello");}@Testpublic void test2() {System.out.println("Hello1");System.out.println("number = " + number);method();int num = showInfo("China");System.out.println(num);}public void method() {System.out.println("method()......");}public int showInfo(String info){System.out.println(info);return 10;}@Testpublic void test3() {Scanner sc = new Scanner(System.in);System.out.println("请输入一个数值");int num = sc.nextInt();System.out.println(num);for(int i = 1; i <= num; i++){System.out.println(i);}}@Testpublic void test4(){System.out.println("Hello4");}@Testpublic void test5(){System.out.println("Hello5");} }
包装类(Wrapper)的使用



基本类型、包装类与String类间的转换



字节码文件可以体现出自动装箱与自动拆箱的过程

包装类缓存对象

面试题1:
public class InterviewTest1 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j); // false//底层都会调用Integer的valueOf()//这个地方取得值是里面已经new好的Integer数组里面的对象,cache数组中每一个位置都是一个new Integer()对象,//所以他们的地址值都是相同的,都是取的cache数组中的第129位Integer m = 1; //自动装箱Integer n = 1;System.out.println(m == n); //true//根据valueOf的源码可知,这个地方的128不在[-128,127]范围内,所以是new Integer(i)的一个对象出来Integer x = 128;Integer y = 128;System.out.println(x == y); //false}
}
cache数组长度是256,循环,cache数组[第一位是-128,第二位是-127.....一直到127]为止

用自动装箱的方式,在这个范围内用==判断的全都是true,出了这个范围是false
面试题2:
public class InterviewTest2 {public static void main(String[] args) {//题目1:int i = 10;double d = 10.2;System.out.println(i == d); //false//题目2:Integer i1 = 10;Double d1 = 10.2;
// System.out.println(i1 == d1); //报错,==可以比较引用类型的地址,但是需要时同一类型//题目3:会进行拆箱,m就会转成int类型的,装箱会成为不同引用类型,会报错Integer m = 1000; //1000先装箱,比较时拆箱double n = 1000;System.out.println(m == n); //true//题目4:Integer x = 1000;int y = 1000;System.out.println(x == y); // true}
}
int(i)类型转换成(to)成double类型(d) i2d

面试题3:
public class InterviewTest3 {public static void main(String[] args) {//这个地方的比较有一个类型兼容的问题,所以输出结果是1.0Object o1 = true ? new Integer(1) : new Double(2.0);System.out.println(o1); //1.0Object o2;if(true)o2 = new Integer(1);elseo2 = new Double(2.0);System.out.println(o2); //1}
}
总结:
包装类的使用 1.为什么要使用包装类? 为了使得基本数据类型的变量具备引用数据类型变量的相关特征(比如:封装性、继承性、多态性),我们给各个基本数据 类型的变量都提供了对应的包装类。 2.(掌握)基本数据类型对应的包装类类型byte -> Byteshort -> Shortint -> Integerlong -> Longfloat -> Floatdouble ->Doublechar -> Characterboolean -> Boolean 3.掌握基本数据类型 与 包装类之间的转换。3.1 为什么需要转换> 一方面,在有些场景下,需要使用基本数据类型对应的包装类的对象。此时就需要将基本数据类型的变量转换为包装类的对象。比如:ArrayList的add(Object obj);Object类的equals(Object obj)> 对于包装类来讲,既然我们使用的是对象,那么对象是不能进行+ - * /等运算的。为了能够进行这些运算,就需要将包装类的对象转换为基本数据类型的变量。3.2 如何转换:(装箱)基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的valueOf(xxxxx)(拆箱)包装类 ---> 基本数据类型: 调用包装类的xxxValue()注意:原来使用基本数据类型变量的位置,改成包装类以后,对于成员变量来说,其默认值变化了!jdk5.0新特性:自动装箱、自动拆箱。4.String 与 基本数据类型、包装类之间的转换。基本数据类型、包装类---> String类型: ① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""String类型 ---> 基本数据类型、包装类:调用包装类的静态方法:parseXxx()
相关代码:代码练习
public class WrapperTest {/*** 基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的value0f(xxx xx)* 包装类 ---> 基本数据类型: 调用包装类的xxxValue()* jdk5.0新特性:自动装箱、自动拆箱。*/@Testpublic void test4(){//自动装箱: 基本数据类型--->包装类int i1 = 10;Integer ii1 = i1;//自动装箱System.out.println(ii1.toString());Integer ii2 = i1 + 1; //自动装箱Boolean bb1 = true;//自动装箱Float f1 = 12.3F;//自动装箱//自动拆箱:包装类---> 基本数据类型int i2 = ii1; //自动拆箱boolean b1 = bb1; //自动拆箱}@Testpublic void test3(){Account account = new Account();System.out.println(account.isFlag1); //falseSystem.out.println(account.isFlag2); //nullSystem.out.println(account.balance1); //0.0System.out.println(account.balance2); //null}@Testpublic void test2(){Integer ii1 = new Integer(10);int i1 = ii1.intValue();i1 = i1 + 1;Float ff1 = new Float(12.3F);float f1 = ff1.floatValue();Boolean bb1 = Boolean.valueOf(true);Boolean b1 = bb1.booleanValue();}@Test//基本数据类型 ---> 包装类: ① 使用包装类的构造器 ② (建议)调用包装类的value0f(xxx xx)public void test1(){int i1 = 10;Integer ii1 = new Integer(i1);System.out.println(ii1.toString()); //10float f1 = 12.3F;f1 = 32.2f;Float ff1 = new Float(f1);System.out.println(ff1.toString()); //32.2String s1 = "32.1";Float ff2 = new Float(s1);// s1 = "abc";
// Float ff3 = new Float(s1); //报异常:NumberFormatExceptionboolean b1 = true;Boolean bb1 = new Boolean(b1);System.out.println(bb1);//true//Boolean这块只要长的跟true不一样就是false了String s2 = "false";s2 = "False123";s2 = "TrUe"; //忽略大小写Boolean bb2 = new Boolean(s2);System.out.println(bb2); //false --> true//推荐使用int i2 = 10;Integer ii2 = Integer.valueOf(i2);Boolean b2 = Boolean.valueOf(true);Float f2 = Float.valueOf(12.3F);}
}
class Account{boolean isFlag1;Boolean isFlag2; //null 包装类double balance1; //0.0Double balance2; //null 包装类 0.0可以理解成这个对象被初始化了
}
相关代码2:
public class WrapperTest1 {/*** 基本数据类型、包装类---> ① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""* String类型 ---> 基本数据类型、包装类:调用包装类的静态方法:parseXxx()*/@Testpublic void test2(){String s1 = "123";int i1 = Integer.parseInt(s1);System.out.println(i1 + 10);String s2 = "true";boolean b1 = Boolean.parseBoolean(s2);//特别的
// String s3 = "123a";
// int i2 = Integer.parseInt(s3); //报错NumberFormatException}@Testpublic void test1(){//方式1:① String类型:调用String的重载的静态方法value0f(xxxxx); ② 基本数据类型的变量 + ""int i1 = 10;String str1 = String.valueOf(i1);System.out.println(str1); //"10"boolean b1 = true;Boolean b2 = b1;String str2 = String.valueOf(b1);String str3 = String.valueOf(b2);//方式2:基本数据类型的变量 + ""String str4 = i1 + "";String str5 = b1 + "";}
}
练习题:
利用Vector代替数组处理:从键盘读入学生成绩(以负数代表输入结束),找出最高分,并输出学生成绩等级。 提示:数组一旦创建,长度就固定不变,所以在创建数组前就需要知道它的长度。而向量类java.util.Vector可以根据需要动 1、创建Vector对象:Vector v=new Vector(); 2、给向量添加元素:v.addElement(Object obj);//obj必须是对象 3、取出向量中的元素:Object obj=v.elementAt(0);注意第一个元素的下标是0,返回值是0bject类型的。 4、计算向量的长度:v.size(); 5、若与最高分相差10分内:A等;20分内:B等;30分内:C等;其它:D等
package com.atguigu12.wrapper.exer;import java.util.Scanner;
import java.util.Vector;/*** ClassName: ScoreTest* Package: com.atguigu12.wrapper.exer* Description:** @Author: shkstart* @Create 2025-03-25 23:46* @Version: 1.0*/
public class ScoreTest {public static void main(String[] args) {//1.创建Vector对象:Vector v= new Vector();Vector v= new Vector();Scanner scanner = new Scanner(System.in);int maxScore = 0; //记录最高分//2.从键盘中获取学生成绩,存放到v中(以负数代表输入结果)while(true){System.out.print("请输入学生成绩(以负数代表输入结束):");int intScore = scanner.nextInt();if(intScore < 0){break;}
// //装箱:int ---> Integer对象
// Integer score = Integer.valueOf(intScore);
// //添加学生成绩到容器v中
// v.addElement(score);//jdk5.0之后,自动装箱v.addElement(intScore);//3.获取学生成绩的最大值if(maxScore < intScore){maxScore = intScore;}}System.out.println("最高分:" + maxScore);//4.依次获取v中的每个学生成绩,与最高分进行比较,获取学生等级,进行输出for(int i = 0; i < v.size(); i++){Object objScore = v.elementAt(i);//方式1:
// Integer integerScore = (Integer)objScore;
// //拆箱
// int score = integerScore.intValue();//方式2:自动拆箱int score = (Integer)objScore;char grade = ' ';if(maxScore - score <= 10){grade = 'A';}else if(maxScore - score <= 20){grade = 'B';}else if(maxScore - score <= 30){grade = 'C';}else {grade = 'D';}System.out.println("student " + i + " score: " + score + " grade: " + grade);}scanner.close();}
}
ctrl+fn+f12或ctrl+f12在当前文件进行搜索,搜索内容可以直接输入

IDEA断点调试


Person p1 = new Person(3); System.out.println(p1.toString());toString()没有重写之前打印的是地址,对于引用数据类型来说,重写之后,打印的是重写之后的方法
总结:
IDEA中调试程序 1.为什么需要Debug? 编好的程序在执行过程中如果出现错误,该如何查找或定位错误呢?简单的代码直接就可以看出来, 但如果代码比较复杂,就需要借助程序调试工具(Debug)来查找错误了。 2. Debug的步骤1、添加断点2、启动调试3、单步执行4、观察变量和执行流程,找到并解决问题
Description:演示1:行断点,测试debug各个常见操作按钮
Description: 演示2: 方法断点
Description:演示3:字段断点
Description:演不4:条件断点

Description:演示7:强制结束
复习:


//底层都会调用Integer的valueOf() //这个地方取得值是里面已经new好的Integer数组里面的对象,cache数组中每一个位置都是一个new Integer()对象, //所以他们的地址值都是相同的,都是取的cache数组中的第129位 //享元设计模式 Integer m = 1; //自动装箱 Integer n = 1; System.out.println(m == n); //true
相关文章:
java学习笔记7——面向对象
关键字:static 类变量 静态变量的内存解析: 相关代码: public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值…...
leetcode day31 453+435
453 用最少数量引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂直 地…...
C++三大特性之继承
1.继承的概念及定义 回忆封装 C Stack类设计和C设计Stack对比。封装更好:访问限定符类的数据和方法放在一起 -> 避免底层接口的暴露,数据更加的安全,程序的耦合性更高迭代器的设计,封装了容器底层结构,在不暴露底层…...
PyQt QDoubleSpinBox控件用法详解
QDoubleSpinBox 是 PyQt中用于输入浮点数的控件,支持键盘输入和上下箭头调整数值。与QtSpinBox不同,QtSpinBox是用于输入整数的控件。 关键属性和方法 QDoubleSpinBox 的关键属性和方法如下表所示: 方法/属性说明setRange(min, max)设置数…...
解决Vmware 运行虚拟机Ubuntu22.04卡顿、终端打字延迟问题
亲测可用 打开虚拟机设置,关闭加速3D图形 (应该是显卡驱动的问题,不知道那个版本的驱动不会出现这个问题,所以干脆把加速关了)...
查询Marklogic数据库,因索引配置造成的返回数据count不同的问题
查询Marklogic数据库,因索引配置造成的返回数据count不同的问题 一,问题: 目前由两个MarkLogic DB,其中A表示所有的数据库统称,包含于BCD; 调用查询接口,通过A和B入口且相同的查询条件去查询B…...
ctfshow做题笔记—栈溢出—pwn73、pwn74
目录 一、pwn73(愉快的尝试一下一把梭吧!) 二、pwn74(噢?好像到现在为止还没有了解到one_gadget?) 前言: 抽空闲时间继续学习,记录了两道题,pwn74卡了几天哈哈。 一、pwn73(愉快的尝试一下一把梭吧!) …...
026-zstd
zstd 以下为Zstandard(zstd)压缩算法从原理到代码实现的技术调研报告,结合流程图、结构图及完整C代码实现: 一、核心原理与技术架构 1.1 算法原理 Zstd基于LZ77衍生算法与熵编码(FSE/Huffman)的混合架构&…...
AF3 quat_to_rot函数解读
AlphaFold3 rigid_utils 模块的 quat_to_rot 函数的功能是把四元数转换为旋转矩阵,函数利用预定义的四元数到旋转矩阵的转换表 _QTR_MAT 来简化计算。 理解四元数到旋转矩阵的转换 源代码: _quat_elements = ["a", "b", "c", "d"]…...
Elasticsearch 的搜索功能
Elasticsearch 的搜索功能 建议阅读顺序: Elasticsearch 入门Elasticsearch 搜索(本文) 1. 介绍 使用 Elasticsearch 最终目的是为了实现搜索功能,现在先将文档添加到索引中,接下来完成搜索的方法。 查询的分类&…...
Vala编成语言教程-构造函数和析构函数
构造函数 Vala支持两种略有不同的构造方案:我们将重点讨论Java/C#风格的构造方案,另一种是GObject风格的构造方案。 Vala不支持构造函数重载的原因与方法重载不被允许的原因相同,这意味着一个类不能有多个同名构造函数。但这并不构成问题&…...
Mybatis-plus配置动态多数据源
前言:微服务架构中,有些模块中可能不同组件用不同数据源,或者做数据库主从集群需要读写分离,动态切换数据源,或不同方法需要不同数据源就需要一个快捷方便的方法。引用动态数据源组件dynamic-datasource-spring-boot-s…...
CSS+JS 堆叠图片动态交互切换
结合DeepSeek提供的代码,终于实现了堆叠两张图片动态循环切换,以下是代码: 通过绝对定位放了两张图片 <div class"col-lg-5" style"z-index: 40; position: relative;"><img src"images/banner_1.png&quo…...
内存检查之Valgrind工具
内存检查之Valgrind工具 Author: Once Day Date: 2025年3月26日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章请查看专栏: Linux实践记录_Once-Day的博客-CSD…...
强大的AI网站推荐(第四集)—— Gamma
网站:Gamma 号称:展示创意的新媒介 博主评价:快速展示创意,重点是展示,在几秒钟内快速生成幻灯片、网站、文档等内容 推荐指数:🌟🌟🌟🌟🌟&#x…...
javafx项目结构+代码规范
javafx项目 1. 新建项目,对项目的理解 jdk: 是 Java Development ToolKit 的简称,也就是 Java 开发工具包。JDK 是整个 Java 的核心,包括 Java 运行环境(Java Runtime Envirnment,简称 JRE)&a…...
国外计算机证书推荐(考证)(6 Sigma、AWS、APICS、IIA、Microsoft、Oracle、PMI、Red Hat)
文章目录 证书推荐1. 六西格玛 (6 Sigma)2. 亚马逊网络服务 (AWS)3. 美国生产与库存控制学会 (APICS)4. 内部审计师协会 (IIA)5. 微软 (Microsoft)6. 甲骨文 (Oracle)7. 项目管理协会 (PMI)8. 红帽 (Red Hat) 证书推荐 1. 六西格玛 (6 Sigma) 介绍:六西格玛是一种…...
黑盒测试与白盒测试详解
黑盒测试和白盒测试是软件测试中两种最基本的测试方法,它们在测试视角、测试重点和适用场景等方面存在显著差异。 一、黑盒测试 1. 基本概念 黑盒测试又称功能测试,将软件视为一个"黑盒子",不关心内部结构和实现细节,只…...
准确--配置服务器文件数
某些系统可能在 /etc/security/limits.d/ 目录下有额外配置覆盖全局设置。检查是否存在冲突文件: ls /etc/security/limits.d/如果有文件(如 90-nproc.conf 或 90-nofile.conf),需编辑或删除这些文件中的冲突配置。 确保系统启用…...
《熔化焊接与热切割作业》考试注意事项
考试前的准备 携带必要的证件和材料:考生需携带身份证、准考证等有效证件,以及考试所需的焊接工具、材料等。确保证件齐全,避免因证件问题影响考试。 提前检查焊接设备和工具:在考试前,考生应仔细检查焊接设备和工具是…...
ROS2的发展历史、核心架构和应用场景
以下是对**ROS2(Robot Operating System 2)**的发展历史、核心架构和应用场景的详细解析,覆盖其技术演变、关键特性和生态系统: 一、ROS2的诞生背景:从ROS1到ROS2 1. ROS1的历史与局限 ROS1的起源: 2007年…...
[unity 点击事件] 区域响应点击事件,排除子节点区域,Raycast Target 应用
当我打开一个二级弹窗后,希望可以通过点击弹窗以外的区域来关闭该弹窗。一开始我是在弹窗主节点上挂载了一个 button 组件,该 button 注册的点击事件中关闭该弹窗。在子节点(一个背景图)的image组件上启用 Raycast Target 选项&am…...
鸿蒙生态全解析:应用适配分享
一、鸿蒙系统的技术底座与适配挑战 HarmonyOS NEXT 作为全场景分布式操作系统,通过统一的技术底座和声明式开发框架,实现了 "一次开发,多端部署" 的跨设备协同能力。其核心优势在于: 弹性部署架构:一套系统…...
el-select 可搜索下拉框 在ios、ipad 无法唤出键盘,造成无法输入
下一篇:el-select 可搜索下拉框,选中选项后,希望立即失去焦点,收起键盘,执行其他逻辑 【效果图】:分组展示选项 >【去界面操作体验】 首先,通过 夸克浏览器的搜索: el-select 在 ipad 输入框…...
深度剖析:域名与DNS安全的全方位解读
导语 在互联网的庞大体系中,域名如同我们访问网络资源的“门牌号”,而DNS则像是将门牌号翻译为具体地址的“翻译官”。然而,这看似平常的域名与DNS系统,却面临着诸多安全风险。一旦遭受攻击,可能导致网站无法访问、用户数据泄露等严重后果。了解域名与DNS安全知识,对保障…...
使用ZMQ和protobuf实现C++程序与Python程序的通信
文章目录 背景一 应用场景与需求二 Protobuf: 跨语言数据交换的基石三 通信方案 ZMQ (ZeroMQ) —— 高性能消息中间件四 进阶: 安全性与性能优化五 实践例子: 工厂温度监控系统5.1 场景描述5.2 Protobuf数据结构定义5.3 C数据采集与发布5.4 Python数据接收与可视化5.5 关键实现…...
Linux实现生产者消费者模型
目录 概念及优势 代码实现 概念及优势 生产者消费者模型是一种用于线程同步的模型,在这个模型中有两种角色,生产者生产数据,消费者消费数据。有三种关系,生产者与生产者,消费者与消费者,生产者与消费者。…...
AI驱动下的智能异常处置:海量多元异构数据的挑战与应对
摘要 在QCon北京会议上,AI驱动的智能异常处置成为焦点。会议深入探讨了平台复杂性及处理海量多元异构数据时所面临的挑战,特别是异常识别与根本原因定位的难题。这些挑战要求技术从业者不断优化算法,以提升数据处理效率和准确性。 关键词 …...
Axure设计之中继器表格——拖动列调整位置教程(中继器)
一、原理介绍 实现表格列的拖动排序,主要依赖Axure的动态面板和中继器两大核心功能: 动态面板交互控制 将表格的列标题封装在动态面板中,通过拖拽事件(开始、移动、结束)捕捉用户操作 在拖拽过程中实时计算鼠标位置&…...
基于大数据的各品牌手机销量数据可视化分析系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,各品牌手机销量数据可视化分析系统当然不能排除在外。基于大数据的各品牌手机销量数据可视化分析系统是在实际应用和软件工程的开发原理之…...
