0721(014天 )
每日一狗(茉莉的日记本)
主标题
文章目录
复习
-
成员变量声明后就有默认值。
- 数值型:0
- 字符型:
' '
,unicode码值为0岁对应的字符 - 布尔值:false
-
临时变量要先创建后赋值,先赋值后使用。
1. 类的奇奇怪怪的知识
1.1 包装类(类属性类型的选择)
- 属性存在默认值,但是简单数据类型的默认值又有可能设定值与默认值相同,你无法判定其到底是默认值还是后来给的值。
- 使用简单类型的包装类
- 引用类型存在默认值但是都是null,这个时候调用其内部的所属方法就会报空指针异常。
- 先赋初值后使用
1.2 句柄操作
带补充
1.3 引用和指针的区别
引用和指针的区别
- 指针是存放内存地址的一个命名空间,可以对其进行修改并操作其他的内存空间数据。
- 通过引用找不到引用指向的地址,不能根据引用操作内存,所以就安全。
1.4 方法传参部分细节
- 方法的返回值类型与上面定义的类型相同,void时只能
return;
来提前结束方法的调用 - 静态方法只能调用静态方法,想调用没静态修饰词的属性或方法之前要先创建对象
- 方法的传参
- 单向值传递:简单数据类型传递的是就是具体的值(有新的临时变量开辟),方法内部对数据进行修改不会对其进行修改
- 引用单向传递:引用数据类型由于其传入的是引用就会将其所指向的数据进行修改。
当内部存在对象新建和覆盖时,源数据不会被修改。
- 无返回值时这默写
return null
不行,null时Object类,还是有返回值的。还是不能跟的
应用继承的建议
建议的使用场景:把通用操作和方法放在父类中,将特殊的方法定义在子类中。
好处在于:1、避免代码重复。2、避免了人为因素导致的不一致性
2. 三种字符串类
- String
- StringBuilder
- StringBuffer
2.1 应用习惯
- 当常量用(基本不变)执行性能够呛
- String
- 频繁修改计算
- 线程安全:StringBuffer,属性
- 不考虑线程安全:StringBuilder,临时变量
2.2 字符串常用方法(一般通用)
String s1 = "abc";
String s2 = new String();// new String("abc");
System.out.println(s1.length());//获取字符串种的字符个数,注意不区分中英文
System.out.println(s1.charAt(0));//获取指定下标位置上的字符
System.out.println(s1.indexOf("a")); //从左向右查找指定参数字符串对应的起始下标位置
System.out.println(s1.lastIndexOf("b"));//从右向左查找指定参数字符串对应的起始下标位置
System.out.println(s1.substring(0,2)); //指定下标参数区间内的子字符串,含左不含右
//字符串拼接
s1="aa"+s1+"!"; //toString
StringBuilder sb1 = new StringBuilder("abc");// new StringBuilder()
// sb1="tttt";语法错误
System.out.println(sb1);
System.out.println(sb1.length());//获取字符串种的字符个数,注意不区分中英文
System.out.println(sb1.charAt(0));
System.out.println(sb1.indexOf("a"));
System.out.println(sb1.lastIndexOf("b"));
System.out.println(sb1.substring(0,2));
sb1.insert(0, "aa").append("!"); //insert在指定位置插入字符串,append在字符串的末尾追加内容
System.out.println("sb1:"+sb1);
sb1.delete(1, 3);//删除指定区间的内容
sb1.deleteCharAt(sb1.length()-1);//删除指定下标位置上的一个字符
System.out.println(sb1);
sb1.replace(0, 1, "1asdfasdfasdfasdf2"); //将指定区间上的字符串转换为参数3字符串
System.out.println(sb1);
//反转字符串
StringBuilder sb11=sb1.reverse();
System.out.println(sb11);
StringBuffer sb2 = new StringBuffer("bbbb");// new StringBuffer();
// sb2="ttt"; 语法错误
System.out.println(sb2.length());//获取字符串种的字符个数,注意不区分中英文
System.out.println(sb2.charAt(0));
System.out.println(sb2.indexOf("a"));
System.out.println(sb2.lastIndexOf("b"));
System.out.println(sb2.substring(0,2));
sb2.insert(0,"aa");
sb2.append("!");
sb2.deleteCharAt(sb2.length()-2);
sb2.delete(1, 3);
sb2.replace(0, 1, "asdfasd");
sb2.reverse();
如果需要使用字符串常量或者修改次数较少,可以使用String
如果需要频繁修改可以考虑使用StringBuilder或者StringBuffer
如果需要考虑线程安全问题则使用StringBuffer,如果没有线程安全问题则直接使用StringBuilder
- 声明
new
- 获取字符串长度
length()
- 获取指定索引字符
charAt(0)
- 截取指定索引范围的字符串
substring(0,2)
- 切片分组
split("拆分字符串")
- 字符串拼接
+、append()
- 曾:插入指定索引
insert(索引,"插入字符串")
- 删:删除指定区间
delete(起点,终点)
- 删:删除指定索引的字符
deleteCharAt(要删除字符的索引)
- 改:用指定字符串替换区间内的字符串
replace(起点,终点,"要替换的字符串")
- 查:查找指定字符串的索引
indexOf("a")、lastIndexOf("b")
继承小练习题
学生老师类
不用继承
class Teacher {
private String name;
private int age;
private String subject;
public void eat() {
System.out.println(name + "正在吃饭");
}
public void teach() {
System.out.println(name + "正在授课");
}
public String toString() {
return "年龄为" + age + "的" + name + "教授科目为" + subject;
}
}
class Student {
private String name;
private int age;
private String class_;
public void eat() {
System.out.println(name + "正在吃饭");
}
public void study() {
System.out.println(name + "正在学习");
}
public String toString() {
return age + "岁的" + name + "在" + class_ + "班内";
}
}
用了继承
public class 继承小练习 {
public static void main(String[] args) {
Teacher t = new Teacher();
t.setName("张老师");
t.setAge(25);
t.setSubject("高数");
System.out.println(t.toString()); // 年龄为25的张老师教授科目为高数
t.eat(); // 张老师正在吃饭
t.teach(); // 张老师正在授课
Student s = new Student();
s.setAge(18);
s.setClass_("3-2020");
s.setName("张三");
System.out.println(s.toString()); // 年龄为18的张三教室为3-2020
s.eat(); // 张三正在吃饭
s.study(); // 张三正在学习
}
}
class Person {
private String name;
private int age;
public String toString() {
return name + "今年" + age + "岁";
}
public void eat() {
System.out.println(name + "正在吃饭");
}
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;
}
}
class Teacher extends Person {
private String subject;
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public void teach() {
System.out.println(this.getName() + "正在授课");
}
public String toString() {
return "年龄为" + this.getAge() + "的" + this.getName() + "教授科目为" + subject;
}
}
class Student extends Person {
private String class_;
public String getClass_() {
return class_;
}
public void setClass_(String class_) {
this.class_ = class_;
}
public void study() {
System.out.println(this.getName() + "正在学习");
}
public String toString() {
return "年龄为" + this.getAge() + "的" + this.getName() + "教室为" + class_;
}
}
加减继承乘除
在java的继承关系中,新的类称为子类,也叫派生类。
定义一个类Calcolate1、实现加减两种运算,在编写一个派生类Calcolate2,实现乘除运算
package com.car;
public class 继承在练习 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calculate1 c1 = new Calculate1();
c1.setNum1(5);
c1.setNum2(6);
System.out.println(c1.add()); // 11
System.out.println(c1.sub()); // -1
Calculate2 c2 = new Calculate2();
c2.setNum1(2);
c2.setNum2(6);
System.out.println(c2.add()); // 8
System.out.println(c2.sub()); // -4
System.out.println(c2.cheng()); // 12
System.out.println(c2.chu()); // 0.3333333333333333
}
}
class Calculate2 extends Calculate1 {
public int cheng() {
return getNum1() * getNum2();
}
public double chu() {
if (getNum2() == 0) {
return 0.0;
}
return 1. * getNum1() / getNum2();
}
}
class Calculate1 {
private int num1;
private int num2;
public int add() {
return num1 + num2;
}
public int sub() {
return num1 - num2;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
}
3. 特殊方法
3.1 main方法
在终端运行的时候可以在运行
也可以在eclipse中设定运行时后面跟的参数
3.2 构造器方法
-
方法名和类名相同(包括大小写)
-
不算成员(不能被继承)
-
不能直接用该类的对象进行调用,只是在用
new
修饰符创建对象的时候,根据传入的参数调用不同的构造器进行对象的创建 -
无返回值,写
void
也不行,方法体内部可以使用return
提前结束方法,但是不能返回任何数据 -
公共的
-
与new运算符一起使用;在创建对象时执行
-
可以有多个构造器
-
参数个数、参数类型、参数类型的顺序 java只能识别参数类型是否相同,不能识别形参明,想下边这种就不行 class Stu{ private String name; private String class_; public Stu(String name, String class_){} public Stu(String class_, String name){} }
-
-
默认有一个无参构造器,但是如果写了一个有参构造器的话,那个无参的构造器就没了,要用就得在写。
-
继承子类的构造方法的执行流程(先运行父类的构造方法在运行子类的构造方法)
这是A类的构造方法 这是B类的构造方法 package com.ketang; public class 继承和构造方法测试 { public static void main(String[] args) { B b = new B(); } } class A { public A() { System.out.println("这是A类的构造方法"); } } class B extends A { public B() { System.out.println("这是B类的构造方法"); } }
3.3 析构器方法(finalize())
jdk10以后不用了
在垃圾回收之前运行的方法-资源回收
垃圾回收器方法无法保证一定会运行,一般不用
官方文档上也不确定啥时候回收对象。
final 常量修饰符
finally Java 中的 Finally 关键一般与try一起使用,在程序进入try块之后,无论程序是因为异常而中止或其它方式返回终止的,finally块的内容一定会被执行 。
finalize 析构器方法
4. 奇奇怪怪的知识
4.1 继承中不能被继承的情况
官方人为完美的类
父类中有一个方法名()
4.2 final修饰符
被声明后一旦被赋值后就不允许在修改(覆盖\重写)
临时变量:赋值了就别想改了
类:不能被继承(继承要干嘛,肯定是父类的东西不支持你的需求,那你肯定是想改其中的方法属性呀,不行)
方法:不允许重写
引用数据类型:可以改内部属性,但是不允许修改引用指向其他对象。
4.3 父子类的歪名
父类、基类、超类
子类、派生类
将通用的放到父类中,子类中一些特殊方法。
避免人为不一致
避免代码重写
4.4 单例设计模式(下限)
饿汉模式:我不管你用不用,反正对象已经创建了,你爱用不用吧!
/*
* 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
* 主要解决:一个全局使用的类频繁地创建与销毁。
* 何时使用:当您想控制实例数目,节省系统资源的时候。
* 单例模式有多种写法,最常见的是懒汉模式和饿汉模式
*/
public class Singleton {
//保证在当前类以外无法创建对象
private Singleton() {}
private final static Singleton instance=new Singleton();
public static Singleton getInstance() {
return instance;
}
}
4.5 static 修饰符
描述类属性时:所有对象都共享改属性
描述类方法时:这个方法就属于这个类了,可以直接使用类点出来,不用在new出来一个对象后再用对象调用方法了。
4.6 成员属性变量和临时变量的差距
成员变量
- 成员变量存在于堆内存的对象中,堆内存中的对象大小可以任意,
- 允许在运行时进行调整。
- 访问速度较慢。(毕竟要先找到对象,在找对象属性)
- 成员变量都有默认初始化值;局部变量没有默认初始化值
局部变量
- 存在与栈内存的方法中,可以快速定位,但是大小是限定的
- 成员变量随着对象的创建而存在,随着对象的表示而消失。局部变量随着所属区域的执行而存在,随着所属区域的结束而释放
扩展小芝士
-
引用和指针的区别
- 指针是存放内存地址的一个命名空间,可以对其进行修改并操作其他的内存空间数据。
- 通过引用找不到引用指向的地址,不能根据引用操作内存,所以就安全。
-
要想工资高,就得篇高并发
-
钩子函数(回调函数)如何理解钩子函数 - 知乎 (zhihu.com)
- 1、是个函数,在系统消息触发时被系统调用
- 2、不是用户自己触发的
- 3、使用时直接编写函数体
-
软件中没有银弹(各种问题通用解决方案)
-
设计模式: 由专家总结出来的在某种情况下解决某类问题的最佳解决方案,是思想、是知识,是一种抽象的内容