猜拳 我的实现
Random r = new Random();
//boolean b = false;
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("请输入0-石头,1-剪刀,2-布");
int rd = r.nextInt(3);
int tom = new Scanner(System.in).nextInt();
//0石头,1剪刀 2布
/*if (i == 1 && tom == 2) {
b = false;
}
if (b) {
if (tom - rd == -1 || tom - rd == 2) {
//tom胜的,先不管。
} else {
//如果 tom为 布。
if (tom == 2) {
//系统为 石头
rd = 0;
} else {
//否则。系统为 tom+1;系统永远输
rd = tom + 1;
}
}
}*/
if (tom == 0) {
System.out.println("你出的是 石头");
} else if (tom == 1) {
System.out.println("你出的是 剪刀");
} else {
System.out.println("你出的是 布");
}
if (rd == 0) {
System.out.println("系统的是 石头");
} else if (rd == 1) {
System.out.println("系统的是 剪刀");
} else {
System.out.println("系统的是 布");
}
if (rd == tom) {
System.out.println("平局");
} else if (tom - rd == -1 || tom - rd == 2) {
//你出是 石头,或者 剪刀。 你出是布
System.out.println("你赢了");
} else {
//你出是石头,对方是 布。
System.out.println("你输了");
}
/*if (rd == tom) {
System.out.println("平局");
} else if (tom == 0 && rd == 1) {
System.out.println("你赢了");
} else if (tom == 1 && rd == 2) {
System.out.println("你赢了");
} else if (tom == 2 && rd == 0) {
System.out.println("你赢了");
} else {
System.out.println("你输了");
}*/
System.out.println("----------------------");
}
idea使用
快捷键
1.删除当前行,自己配置ctrl + d
2.复制当前行,自己配置ctrl + alt+向下光标3.补全代码alt+/
4、添加注释和取消注释 ctrl +/【第一次是添加注释,第二次是取消注释】
6.快速格式化代本ctrl + alt +L
7.快速运行程序自己定义alt +R
8.生成构造器等alt + insert[提高开发效率]
9.查看一个类的层级关系ctrl+H[学习继承后,非常有用]
- 就是 结构窗口,alt+7
10.将光标放在一个方法上,输入ctrl + B,可以选择定位到哪个类的方法[学继承后,非常有用]
- Eclips 快捷键模式,按住Ctrl单击 或 ctrl+T
11.自动的分配变量名,通过在后面.var
●模板/自定义模板
·file -> settings -> editor->Live templates ->查看有哪些模板快捷键/可以自己增加模板
动态绑定
属性看编译类型,方法看运行类型
public class PolyExercise02 {
public static void main(String[] args) {
Sub s = new Sub();
System.out.println(s.count);//20
s.display();//20
Base b = s;
System.out.println(b == s);//T
System.out.println(b.count);//10
b.display();//20
}
}
class Base {//父类
int count = 10;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base {//子类
int count = 20;
public void display() {
System.out.println(this.count);
}
}
调用自己的方法和属性
public class DynamicBinding {
public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
A a = new B();//向上转型
System.out.println(a.i);
System.out.println(a.sum());//?40
System.out.println(a.sum1());//?30
//10
//40
//30
}
}
class A {//父类
public int i = 10;
//动态绑定机制:
public int sum() {//父类sum()
return getI() + 10;//20 + 10
}
public int sum1() {//父类sum1()
return i + 10;//10 + 10
}
public int getI() {//父类getI
return i;
}
}
class B extends A {//子类
public int i = 20;
public int sum() {
return i + 20;
}
public int getI() {//子类getI()
return i;
}
public int sum1() {
return i + 10;
}
}
/*public int sum() {
return i + 20;
}*/
/*public int sum1() {
return i + 10;
}*/
10
30 //getI获取的是子类的 20
20 //直接用 i,用的是 编译类型的,A类的i为10
java的动态绑定机制
1.当调用对象方法的时候,该方法会和该对象的内
存地址/运行类型绑定
2.当调用对象属性时,没有动态绑定机制,哪里声
明,那里使用
instanceof
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("mary", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);
//循环遍历多态数组,调用say
for (int i = 0; i < persons.length; i++) {
//老师提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有JVM来判断
System.out.println(persons[i].say());//动态绑定机制
//这里大家聪明. 使用 类型判断 + 向下转型.
if(persons[i] instanceof Student) {//判断person[i] 的运行类型是不是Student
Student student = (Student)persons[i];//向下转型
student.study();
//小伙伴也可以使用一条语句 ((Student)persons[i]).study();
} else if(persons[i] instanceof Teacher) {
Teacher teacher = (Teacher)persons[i];
teacher.teach();
} else if(persons[i] instanceof Person){
//System.out.println("你的类型有误, 请自己检查...");
} else {
System.out.println("你的类型有误, 请自己检查...");
}
}
String equals
//把Object的equals方法重写了,变成了比较两个字符串值是否相同
public boolean equals(Object anObject) {
if (this == anObject) {//如果是同一个对象
return true;//返回true
}
if (anObject instanceof String) {//判断类型
String anotherString = (String)anObject;//向下转型
int n = value.length;
if (n == anotherString.value.length) {//如果长度相同
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {//然后一个一个的比较字符
if (v1[i] != v2[i])
return false;
i++;
}
return true;//如果两个字符串的所有字符都相等,则返回true
}
}
return false;//如果比较的不是字符串,则直接返回false
}
public boolean equals(Object obj) {
return (this == obj);
}//object类的
//Integer 类型的
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
对象重写 equals
//重写Object 的 equals方法
public boolean equals(Object obj) {
//判断如果比较的两个对象是同一个对象,则直接返回true
if(this == obj) {
return true;
}
//类型判断
if(obj instanceof Person) {//是Person,我们才比较
//进行 向下转型, 因为我需要得到obj的 各个属性
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
}
//如果不是Person ,则直接返回false
return false;
}
toString源码
// Object的toString() 源码
(1)getClass().getName() 类的全类名(包名+类名 )
(2)Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
finalize()
1.当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,
做一些释放资源的揉作
·2.什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃
圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。
3.垃圾回收机制的调用,是由系统来决定(即有自己的GC算法).
也可以通过System.gc() 主动触发垃圾回收机制,
//演示 Finalize的用法
public class Finalize_ {
public static void main(String[] args) {
Car bmw = new Car("宝马");
//这时 car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象, 在销毁对象前,会调用该对象的finalize方法
//,程序员就可以在 finalize中,写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文件..)
//,如果程序员不重写 finalize,那么就会调用 Object类的 finalize, 即默认处理
//,如果程序员重写了finalize, 就可以实现自己的逻辑
bmw = null;
System.gc();//主动调用垃圾回收器
System.out.println("程序退出了....");
}
}
class Car {
private String name;
//属性, 资源。。
public Car(String name) {
this.name = name;
}
//重写finalize
@Override
protected void finalize() throws Throwable {
System.out.println("我们销毁 汽车" + name );
System.out.println("释放了某些资源...");
}
}
程序退出了....
我们销毁 汽车宝马
释放了某些资源...
断点调试
F7跳入),跳入方法内
F8(跳过),逐行执行代码
shift+F8(跳出),跳出方法
F9(resume,执行到下一个断点)
类静态变量
public class ChildGame {
public static void main(String[] args) {
Child child1 = new Child("白骨精");
child1.join();
child1.count++;
Child child2 = new Child("狐狸精");
child2.join();
child2.count++;
//类变量,可以通过类名来访问
System.out.println("共有" + Child.count + " 小孩加入了游戏...");
System.out.println("child1.count=" + child1.count);//3
System.out.println("child2.count=" + child2.count);//3
}
}
class Child { //类
private String name;
//定义一个变量 count ,是一个类变量(静态变量) static 静态
//该变量最大的特点就是会被Child 类的所有的对象实例共享
public static int count = 0;
public Child(String name) {
this.name = name;
}
}
所有的类,都指向这一个变量。
共识(1) static变量是同一个类所有对象共享(2) static类变量,在类加载的时候就生成了.
- 堆里的一块 公共区域。JDK8和以后
- 类对应的 class对象,最后加载
- 可以看到static变量保存在Class 实例的尾部。
- Class对象确实在堆中。
- 放在 方法区的 一个块 静态域里。JDK8以前。
main方法接收参数
D: \javacode>java Hello tom jack smith
第1个参数=tom
idea 项目的运行文件,设置里:
VM options:
Program arguments:北京 上海 天津 tom jack
代码块
1)相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
2)场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性
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;
//3个构造器-》重载
//老韩解读
//(1) 下面的三个构造器都有相同的语句
//(2) 这样代码看起来比较冗余
//(3) 这时我们可以把相同的语句,放入到一个代码块中,即可
//(4) 这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
//如果是静态代码块,只调用一次。
//(5) 代码块调用的顺序优先于构造器..
{
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) {
this.name = name;
this.price = price;
}
}
电影屏幕打开...
广告开始...
电影正是开始...
Movie(String name) 被调用...
===============
static代码块也叫静态代码块,作用就是对类进行初始化,而且它随
着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行。
类什么时候被加载[重要背!]
1 创建对象实例时(new)
2 创建子类对象实例,父类也会被加载
3 使用类的静态成员时(静态属性,静态方法)
- 会先 加载父类的 静态代码块 (先初始化父类)
如果只是使用类的静态成员时,普通代码块并不会执行
- 普通代码块,在new对象时,被调用,而且是每创建一个对象,就调用一次
- 普通代码块,是 构造器的补充。构造器 被调用,才被调用。
静态和普通代码块
public class CodeBlockDetail02 {
public static void main(String[] args) {
A a = new A();// (1) A 静态代码块01 (2) getN1被调用...(3)A 普通代码块01(4)getN2被调用...(5)A() 构造器被调用
}
}
class A {
{ //普通代码块
System.out.println("A 普通代码块01");
}
private int n2 = getN2();//普通属性的初始化
static { //静态代码块
System.out.println("A 静态代码块01");
}
//静态属性的初始化
private static int n1 = getN1();
public static int getN1() {
System.out.println("getN1被调用...");
return 100;
}
public int getN2() { //普通方法/非静态方法
System.out.println("getN2被调用...");
return 200;
}
//无参构造器
public A() {
System.out.println("A() 构造器被调用");
}
}
1调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
②调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
③调用构造方法。
有子类和父类的时候
我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
②子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
③父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4父类的构造方法
⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
⑥子类的构造方法/面试题
普通代码块 调用所有
class C02 {
private int n1 = 100;
private static int n2 = 200;
private void m1() {
}
private static void m2() {
}
static {
//静态代码块,只能调用静态成员
//System.out.println(n1);错误
System.out.println(n2);//ok
//m1();//错误
m2();
}
{
//普通代码块,可以使用任意成员
System.out.println(n1);
System.out.println(n2);//ok
m1();
m2();
}
}