java基础
1. 变量:
分为成员变量(静态、实例)和局部变量
内存中的一块区域,用来存放要处理的数据。
2. 数据类型
基本数据类型:
// 整数默认是int,小数默认是double,需要在后面写明
long l = 232131231L;
float f = 1.1f;
引用数据类型:
3. 关键字(keywords):java定义好的,不可用作变量名
标识符:自己起的变量名(小写开头)、类名(大写开头)
4. 方法重载:名称相同,形参不同(类型、个数、顺序不同)
5. 在无返回值的方法中使用return,提前结束方法 (卫语言风格)
public static int div(int a,int b){
if(b==0){
return 0;
}
return a/b;
}
6. 类型转换:
自动类型转换:
强制类型转换: 可能出现数据溢出
浮点型转整型,去掉小数,只保留整数。
// 强制类型转换
int i = 10;
byte d = (byte) i;
7. 自动类型转换的默认规则
一旦计算,byte,short,char就默认转换成int进行运算
+= -=等蕴含强制类型转换
8. 三元运算符
// 如果a>b,输出a,否则输出b
int c = a > b ? a : b;
9. &&和||是短路与、短路或,如果&&左边为非,右边就不再执行
&和|两边都会执行
10. switch case语句不支持double、float、long
case 语句不支持变量,就是case b:这种,要是字面量(具体值)
具有穿透性,如果没有break会一直执行下去
11. do...while语句,先do再判断
12. 随机数生成
// 方法1
public class demoo {
public static void main(String[] args) {
int r = (int)(Math.random() * 100) + 1;
System.out.println(r);
}
}
// 方法2
import java.util.Random;
Random r = new Random();
int t = r.nextInt(100) + 1;
13.验证码生成
package com.test01;
public class yanzhengma {
public static void main(String[] args) {
String code = Code(8);
System.out.println(code);
}
public static String Code(int n){
String code = " ";
for(int i = 0 ; i<n ; i++){
int type = (int )(Math.random() * 3);
switch (type){
case 0:
code += (int)(Math.random() * 10);
break;
case 1:
int r1 = (int)(Math.random() * 26);
code += (char)('a' + r1);
break;
case 2:
int r2 = (int)(Math.random() * 26);
code += (char)('A' + r2);
break;
default:
}
}
return code;
}
}
14.数组的静态初始化:定义数组的时候,数据已经确定好了
数组的动态初始化:在运行时根据需要动态地创建数组并分配内存,而不是在编译时就固定数组的大小,只确定数组的数据类型和数组长度
(1)数据类型[] 数组名 = new 数据类型[长度]
其中byte short char int long默认为0, float默认为false, 类、接口、数组、string默认为null
int[ ] arr = new int[ ]{12,24,36}
(2)使用Arrays.copyOf
动态扩展数组长度,
int[] newArray = Arrays.copyOf(originalArray, newSize);
(3)使用ArrayList
ArrayList<Integer> list = new ArrayList<>();
while(true){
int num = sc.nextInt();
if (num == 0){
break;
}
list.add(num);
}
System.out.println(list);
15. 随机数的取法
String[] names = new string[]{"张三”,“李四”,"王五”}
int index = (int)(Math.random()*names.length);
16. 求素数的时候,遍历2到n/2的数即可,甚至可以到根号n
如果一个数n有因子(除了1和自身),那么至少有一个因子小于等于n的平方根。因此,只需要检查到n的平方根即可。但是这里的代码写成了n/2,实际上可以优化为更小的范围,即检查到√n。
i <= Math.sqrt(n)
for (int i = 2; i<n/2 ; i++){
if(n%i == 0){
return false;
}
}
17. Scanner用法
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
int number = scanner.nextInt();
double decimal = scanner.nextDouble();
scanner.nextLine(); // 消耗换行符
String line = scanner.nextLine();
18. 通过这种方式可以让a[i]的查找次数减少
for(int i=1 ; i<a.length ; i++){
double temp = a[i];
if(max < temp){
max = temp;
}
if(min > temp){
min = temp;
}
}
面向对象
1. static 修饰成员变量
static修饰方法:
只是为了做一个功能,不需要访问对象的,直接定义成静态方法
用静态方法而不用实例方法,可以避免创建对象,浪费内存
提高了代码的复用性;调用方便,提高开发效率
public class VerifyCodeUtil{
//工具类没有创建对象的必要性 私有化构造器
private VerfyCodeUtil(){
}
... ...
}
注意事项:(1)静态方法中可以直接访问静态成员(静态变量和静态方法),不可以直接访问实例成员;(2)实例方法中可以直接访问静态成员和实例成员;(3)实例方法中可以出现this,静态方法中不可以出现this(this指代的是对象)
2.对于工具,可以新建一个类文件。
3.继承
父类=基类=超类
子类=派生类
子类继承父类的非私有成员(成员变量,成员方法),子类对象其实是由子类和父类多张设计图共同创建出来的对象。
继承的特点:单继承,多层继承,就近原则。
只能继承一个父类,所有的类都是Object类的子类,优先访问自己的类再访问父类
super.指定调用父类方法
方法重写:方法名称、形参一致,重写,建议在前面加@Override
子类重写的访问权限要大于等于父类的,返回值类型要一致或比之前的小
私有方法、静态方法不能被重写
Student s = new Student();
System.out.println(s);
// 这里默认输出的是对象s的地址,因为默认继承Object类,s其实是s.toString()
//于是常重写toString方法
@Override
public String toString(){
return "Student name: " + name + " age: " + age;
}
可以右键->generate->toString
子类构造器的特点:1.必须先调用父类的构造器,再执行自己的;2.子类默认只会调用父类的无参构造函数
class Zi extends Fu(){
public Zi(){
// super(); //默认调用无参,这句无论写不写,默认有。但如果父类没写无参构造,super就必须写
super(10); //这是调用有参
}
}
class Fu(){
public Fu(){
}
public Fu(int n){
}
}
this调用兄弟构造器,即本类中的其他构造器
4.多态
多态是继承/实现情况下的一种状态,包括对象多态和行为多态。
多态的前提:有继承/实现关系;存在父类引用子类对象;存在方法重写。
// 方法: 编译看左边,运行看右边
// 成员变量看父类的,子类要加this.
//对象多态
Animal a1 = new Wolf();
Animal a2 = new Cat();
//方法多态,子类里重写了方法
a1.run();
a2.run();
多态情况下,右边的对象是解耦合的,便于拓展和维护;;;但是多态下不能使用子类独有的行为
多态下的类型转换:
// 自动类型转换
父类 变量名 = new 子类();
// 强制类型转换
子类 变量名 = (子类) 父类变量;
// 非法参数异常
public static void main(String[] args) {
try {
Card c = new GoldCard(1, "李雷", "138", 3000); // 触发异常
} catch (IllegalArgumentException e) {
System.out.println("创建失败:" + e.getMessage());
}
}
demo
main:
package com.demo01;
import java.util.Scanner;
public class CardTestDemo {
public static void main(String[] args) {
Card p1 = new GoldCard(1, "张三", "123-4567", 5500);
Card p2 = new SilverCard(2, "李四", "143-9870", 2500);
//Card p3 = new SilverCard(2, "李四", "143-9870", 500);
Card p[] = new Card[3];
p[0] = p1;
p[1] = p2;
Scanner sc = new Scanner(System.in);
System.out.println("请输入id");
int inputId = sc.nextInt();
Card ca = searchById(inputId, p);
if(ca == null){
System.out.println("卡号不存在");
return;
}
System.out.println("请输入消费金额");
float amount = sc.nextFloat();
System.out.println("余额:" + ca.pay(amount));
}
public static Card searchById(int id, Card[] p){
for(int i=0 ; i<p.length ; i++){
Card t = p[i];
if( t.getId() == id ){
System.out.println(t.toString());
return t;
}
}
return null;
}
}
Card:
package com.demo01;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Card {
private int id;
private String name;
private String number;
private float money;
@Override
public String toString() {
return "卡号:" + id + " 姓名:" + name + " 余额:" + money;
}
protected void deduct(float amount){
if (amount > this.money){
System.out.println("余额不足");
return ;
}
this.money -= amount;
}
public float pay(float price){
return this.money - price;
}
}
GoldCard:
package com.demo01;
public class GoldCard extends Card{
public GoldCard() {
}
public GoldCard(int id, String name, String number, float money) {
super(id, name, number, money);
if (money < 5000) {
throw new IllegalArgumentException("金额不足,无法办银卡");
}
}
@Override
public float pay(float price){
float amount = price * 0.8f;
if (price > 200){
System.out.println("打印免费洗车票");
}
deduct(amount);
return this.getMoney();
}
}
Silver:
package com.demo01;
public class SilverCard extends Card{
public SilverCard(){
}
public SilverCard(int id, String name, String number, float money){
super(id, name, number, money);
if (money < 2000) {
throw new IllegalArgumentException("金额不足,无法办银卡");
}
}
@Override
public float pay(float price){
float amount = price * 0.9f;
deduct(amount);
return this.getMoney();
}
}
面向对象高级
final
修饰类:最终类,不能再被继承 final class Tool{}
修饰方法:最终方法,不能被重写 public final void show(){}
修饰变量:最终变量。只能被赋值一次。
修饰静态变量,会记作常量;修饰实例变量一般无意义。
public static final String STUDENT_NAME = "Lee";
常量
使用了static final修饰的成员变量,常用于记录系统的配置信息。
定义时必须赋初始值
常在Constant.java包里定义各种常量,使用时,可用Constant.SYSTEM_NAME调用。
程序编译后,常量会被“宏替换”,出现常量的地方会被替换成记住的自变量,保证常量和直接使用字面量的性能一样。
单例设计模式
一种软件设计模式,最优解法,一共有23种
确保某个类只能创建一个对象:任务管理器
方法一:拿对象时,对象已经创建好了
public class A { // 2.定义一个静态变量,用于记录本类的一个唯一对象 // 2.1 方法一,加了final,外界就不能修改了 // public static final A a = new A(); // 2.2 方法二,提供公开的静态方法,返回唯一的对象,main通过A.getInstance获得对象 private static A a = new A(); public static A getInstance(){ return a; } // 1.私有化构造器 private A(){ } }
方法二:用对象时,对象刚开始创建
public class A { // 定义一个类变量 public static A a; public static A getInstance(){ if (a == null){ a = new A(); } return a; } // 1.私有化构造器 private A(){ } }
枚举
先罗列名称,里面本质上是常量
枚举都是最终类,不可以被继承,但它默认继承java.lang.Enum类
枚举类的构造器都是私有的,对外不能创建对象
public enum A{
X, Y, Z;
... ...
}
用A.X调用
抽象类
抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类
特点:抽象类不能创建对象,只可以作为一种特殊的父类,让子类继承并实现
一个类继承抽象类,必须重写完抽象类的所有抽象方法,否则这个类也必须定义为抽象类
abstract 修饰类、方法
// 抽象类
public abstract class A{
// 抽象方法,只有方法签名,不能有方法体(大括号)
public absctact void test();
}
设置抽象类是为了更好的多态。父类知道子类有某个行为,但不一样。
模版方法设计模式
重写子类的方法,调用父类方法后子类重写的优先级更高
模版方法是给子类直接使用的,不能被子类重写,一旦重写就失效了,所以建议加final
接口
接口是用来被类实现(implements)的,实现接口的类被称为实现类,一个类可以同时实现多个接口,但必须重写全部接口的全部抽象方法,否则这个类必须定义为抽象类
public class implements Interface01,Interface02,...{ }
jdk8之前,接口只能写 常量 和 抽象方法
接口不能创建对象
public interface A{
// 定义常量可以省略public static final,默认加上去
String NAME = "test";
// 定义方法可以不写public abstract
void show();
}
好处:弥补了类单继承的不足,一个类可以实现多个接口,有多个角色,使功能更强大
可以面向接口编程,更利于解耦合
一份接口demo
package com.interfacedemo.demo1;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Student[] stu = {
new Student("张三", "男", 60),
new Student("李四", "女", 100),
new Student("王五", "男", 80)
};
Scanner sc = new Scanner(System.in);
System.out.println("请输入:\n 1:方案1\n 2.方案2");
int choice = sc.nextInt();
StudentStatistics f = null;
switch (choice) {
case 1:
f = new BasicStatistics();
break;
case 2:
f = new AdvancedStatistics();
break;
default:
System.out.println("请重新输入");
}
f.printInfo(stu);
System.out.println(f.printAvg(stu));
}
}
package com.interfacedemo.demo1;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private String name;
private String sex;
private int score;
}
package com.interfacedemo.demo1;
public class BasicStatistics implements StudentStatistics {
@Override
public void printInfo(Student[] stu) {
for(Student s: stu){
System.out.println("学生姓名:" + s.getName() + "\t性别:" + s.getSex() + "\t成绩:" + s.getScore());
}
}
@Override
public int printAvg(Student[] stu){
int length = stu.length;
int total = 0;
for(Student s: stu){
total += s.getScore();
}
return total / length;
}
}
package com.interfacedemo.demo1;
public class AdvancedStatistics implements StudentStatistics {
@Override
public void printInfo(Student[] stu) {
int girl = 0;
int boy = 0;
for(Student s: stu){
if ("女".equals(s.getSex())){
girl++;
}else if("男".equals(s.getSex())){
boy++;
}else{
System.out.println("不存在的性别");
}
System.out.println("学生姓名:" + s.getName() + "\t性别:" + s.getSex() + "\t成绩:" + s.getScore());
}
System.out.println("女生人数:" + girl + "\t男生人数" + boy);
}
@Override
public int printAvg(Student[] stu){
int length = stu.length;
int total = 0;
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(Student s: stu){
int temp = s.getScore();
if(temp > max){
max = temp;
}
if(temp < min){
min = temp;
}
total += s.getScore();
}
total = total - max - min;
return total / (length-2);
}
}
package com.interfacedemo.demo1;
public interface StudentStatistics {
void printInfo(Student[] stu);
int printAvg(Student[] stu);
}