目录
1.数据类型和运算符
1.1.八大数据类型
- int、double、float、long、boolean、char、short、byte
1.2.自动与强制类型转换
- 自动:小类型转大类型
- 强制:大类型转小类型(需要在小类型范围内)。通过()转换,如double 转 int
- 基本类型的值和字符串连接时,会自动转换为字符串
double num1 = 1.2;
int num2 = (int)num1;
System.out.println(num2);
自动类型提升,整个算术表达式中的类型会自动提升到最高等级操作数同样的类型
1.3.运算符
1.3.1.算数运算符
- +、-、*、/(当除数与被除数都为整型时,除数不能为0,并且结果会自动取整。而当有一个为浮点型时,此时除数可以为0,结果是自然除法的结果。)、%、++、--
1.3.2.赋值运算符
- =(支持连续赋值)、+=、-=(支持表达式的结果赋值)
1.3.3.位运算符
- &、|、~、^、<<、>>、>>>
1.3.4.比较运算符
- > 、<、>=、<=、!=
1.3.5.逻辑运算符
- &&、||、!
1.3.6.三目运算符
- 表达式(布尔类型)? 结果1: 结果2
int a = 10, b =20;
return a>b ? true : false;//将返回false
2.流程控制与数组
2.1.顺序结构
- 自上而下依次执行
2.2. 分支结构
2.2.1.if else语句
int a = 1, b = 2, c = 3;
if(a == 1) System.out.println(a);
else if(b == 2) System.out.println(b);
else System.out.println(c);
结果只会输出1,if else 语句,只要有一个成立,其他的便不会再执行
switch(整型/char类型)
- case (int/char) :表达式;break;(根据具体情况,看是否需要break,如果没有break,语句会一直执行,直到遇到break)
- default:表达式(表示没有相匹配的结果);break;
2.3.循环
- 循环:在满足情况的条件下重复执行某一段代码
- for(表达式1;表达式2(bool,true则执行,false则结束);表达式3)
- while(bool表达式){}先判断在执行
- do{}while(bool表达式);(结尾有一个“;”一定要加)先执行在判断
嵌套循环
for(int i = 1; i < 10; i++) {
for(int j = i; j < 10; j++) {
System.out.print(i + "*" + j + " ");
}
System.out.println();
}
2.4.控制循环结构
2.4.1.break:跳出循环,并且不再执行
2.4.2.continue 跳过此次循环,倘若执行表达式仍满足,则继续执行
2.4.3.return结束循环(多在方法中使用)
2.5.数组
2.5.1.一维数组
- 也是一种类型,要求数组中的所有元素类型相同
- 基本类型数组,复杂类型数组(类数组)
int[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
Arrays.sort(array);
for(int x : array) {
System.out.println(x);
}
public class Sort_1 {
public String number;
public int score;
public Sort_1(String number, int score) {
this.number = number;
this.score = score;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Sort_1 [] array = {new Sort_1("22170001", 99),
new Sort_1("22170002", 100),
new Sort_1("22170003", 98),
new Sort_1("22170024", 88),
new Sort_1("22170027", 95),
};
for(Sort_1 s : array)
System.out.println(s.number + " " + s.score);
2.5.2.二维数组
2.5.2.1.二维数组可以理解为数组的数组,比如说int类型数组,int[] [],可以把int[]当作一种类型,然后这种类型创建了一个数组
Java语言里的数组类型是引用类型,因此数组变量其实是一个引用,这个引用指向真实的数组内存
2.6.foreach
foreach(int x in array){//c#
console.writeLine(x)
}
for(int x : array){//java
System.out.Println(x);
}
同c#不同的是for代替了foreach,:代替了in
3.面向对象(类class)
3.1.定义类、成员变量和方法
public class Review {
public String name;
public int age;
public void getInform() {
System.out.println(this.name + " " + this.age);
}
public static void main(String[] args) {
Review r = new Review();
r.age = 20;
r.name = "Kitty";
r.getInform();
new Review().getInform();
}
}
3.2.创建并使用对象
- Java通过new构造器创建对象,new是java关键字,为调用它的对象创建内存空间,并且调用构造器
3.3.对象和引用
- 对象其实类似c/c++中的指针,只不过它被Java封装成了引用而已
3.4.方法
3.4.1.被static修饰的方法
- 被static修饰的方法称为静态方法,它属于类级别方法,只能被类级别变量调用,对象和实例无法访问到
- 不被static修饰的方法,必须属于类或对象,因为此类方法的存在就是被二者调用的
3.5.递归方法
- 递归:一个方法内调用自身(隐式循环)
public static void isBinary(int n) {
int r = n % 2;
if(n >= 2) {
isBinary(n/2);
}
System.out.print(r);
}
这段代码将十进制转换为2进制就利用了递归
3.6.方法重载
- 重载:方法名相同,参数不同(用于告诉jvm到底调用哪个方法)
3.7.成员变量和局部变量
- 成员变量:类里定义的变量(有无static,有static称作类变量,无称作实列变量)
- 局部变量:方法里定义的变量
int a = 10;
while(true) {
int j = 10;
}
System.out.println(a + j);//将会报错,j是个不合法的变量
3.8.面向对象编程语言的三大特性
3.8.1.封装
- 封装:将信息隐藏在类内部,通过类提供的方法来实现对该信息的访问
- 作用
- 限制不合理访问
- 隐藏实现细节,通过方法进行安全访问
- 可进行数据检查,从而保证对象信息的完整性
- 便于修改,利于维护
public class EncapTest {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
if(age > 0 && age < 200) {
return age;
} else {
return 0;
}
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
EncapTest num1 = new EncapTest();
EncapTest num2 = new EncapTest();
num1.setName("c++");
num1.setAge(20);
num2.setName("java");
num2.setAge(-20);//加上逻辑判断使对象更符合实际
System.out.println(num1.getName() + " " + num1.getAge());
System.out.println(num2.getName() + " " + num2.getAge());
}
}
3.8.1.1.访问修饰符
- private:同一个类内
- protect:同一个类、子类、包中
- public:任意
- default:同一个类、包(包访问修饰符,自动添加,只有同包之内的可以访问)
3.8.2.继承
class Animal{
public void beat() {
System.out.println("pengpeng~~~");
}
public void breath() {
System.out.println("huhuhu~~~");
}
}
public class Cat extends Animal{
public void getInform() {
beat();
breath();
}
public static void main(String[] args) {
Cat num1 = new Cat();
num1.getInform();
}
}
对象a将可以访问到父类中的public修饰的内容,但是没法访问到构造器等
3.8.2.1.重写
- 重写父类方法,子类可以重写父类中存在的方法,并且根据对象调用
class Animal{
public void breath() {
System.out.println("huhuhu~~~");
}
}
public class Cat extends Animal{
public void breath() {
System.out.println("gulugulu~~~");
}
public void getInform() {
breath();
}
}
子类中也有一个getInform方法,但是运行发现并不会冲突,这是因为子类重载了父类的方法。
3.8.2.2.重载
- 子类与父类方法的重载
class Animal{
public void breath() {
System.out.println("huhuhu~~~");
}
}
public class Cat extends Animal{
public void breath(String name) {
System.out.println(name + " gulugulu~~~");
}
public void getInform() {
breath("Kitty");//根据参数调用被重载的方法
breath();
}
public static void main(String[] args) {
Cat num1 = new Cat();
num1.getInform();
}
}
3.8.2.3.super
- super:用于调用父类构造器(先后顺序:存在super时先调用父类构造器,再调用自己)
class Animal{
public void breath() {
System.out.println("huhuhu~~~");
}
}
public class Cat extends Animal{
public void breath() {
System.out.println("gulugulu~~~");
}
public void getInform() {
super.breath();
breath();
}
public static void main(String[] args) {
Cat num1 = new Cat();
num1.getInform();
}
}
- super不能出现在static修饰的方法中
- super访问父类中被隐藏的实例变量
class Animal{
public String name = "hello world";
}
public class Cat extends Animal{
public String name = "Kitty";
public void getInform() {
System.out.println("I am "+ this.name);
System.out.println(super.name);
}
public static void main(String[] args) {
Cat num1 = new Cat();
num1.getInform();
}
}
子类定义一个私有变量,主方法调用子类私有变量将报错,但是通过向上转型可以访问到父类中被覆盖的变量
class Animal{
public String name = "hello world";
}
class Cat extends Animal{
private String name = "cat";
}
public class HideTest {
public static void main(String[] args) {
Cat num1 = new Cat();
System.out.println(num1.name);//会报错
System.out.println(((Animal)num1).name);
}
}
- super 和 this 同时使用存在的问题
class Super{
public String num;
public Super() {
}
public Super(String num) {
this.num = num;
}
}
public class SuperTest extends Super{
public int score;
public SuperTest() {
this(100);//this用于调用自身重载的构造器,而super用于调用父类的构造器
}
public SuperTest(int score) {
//this();//this 和 super不能同时出现否则会报错
super("10001");//super必须放在构造器最顶端
this.score = score;
}
public static void main(String[] args) {
}
}
3.8.3.多态
3.8.3.1.多态相关概念
- 编译时类型:声明该变量时使用的类型决定,运行时类型:实际赋给该变量的对象决定
class Super{
}
public class SubTest extends Super{
public static void main(String[] args) {
Super num1 = new SubTest();
}
}
上述代码中Super就是编译时类型,SubTest就是运行时类型
3.8.3.2.多态发生条件
- 存在继承关系,存在向上转型,存在编译和运行时类型不同
- 向上转型:子类对象赋值给父类引用变量(如上述代码,创建的SubTest对象赋值给了Super引用变量num1)
多态的发生有哪些变化
- 实例变量
class Super{
public int price = 100;
}
public class SubTest extends Super{
public int price = 100;
public static void main(String[] args) {
Super num1 = new SubTest();
System.out.println(num1.price);
}
}
通过编译运行我们发现,num1调用的是Super类的price实例变量。
- 方法
class Super{
public void base() {
System.out.println("base");
}
public void test() {
System.out.println("base_test");
}
}
public class SubTest extends Super{
public void sub() {
System.out.println("sub");
}
public void test() {
System.out.println("sub_test");
}
public static void main(String[] args) {
Super num1 = new SubTest();
num1.base();//执行的是Super中的base方法
num1.sub();//将会报错。报错内容是(sub方法在Super类型中不存在)
num1.test();//执行的是SubTeset中的test方法
}
}
总结:多态发生时,编译时先判断编译类型中是否存在该方法,存在则在运行时判断运行类型中是否存在该方法,如果存在则执行运行类型中的该方法。倘若不存在,则执行编译时类型中的该方法。如果只在运行时类型中存在,则会报错。因此一定要分清编译时类型和运行时类型。
引用变量在编译时只能调用其编译类型所具有的方法。但是在运行时则执行它运行时类型中具有的方法
3.8.4.强制类型转换
Super num2 = new Super();
SubTest num3 = new SubTest();
num2 = (Super)num3;
num3 = (SubTest)num2;
3.8.5.instanceof运算符
- instanceof前面一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(接口)用于判断前面对象是否是后面的类,或者其子类、实现类的实例。返回一个布尔类型值
public class InstanceTest {
public static void main(String[] args) {
Object num1 = new Object();
String str = "Hello world";
System.out.println(num1 instanceof Object);//true,num1是Object类的实例
System.out.println(str instanceof String);//true,str是String类的实例
System.out.println(str instanceof Object);//true,String继承自Object,因此也是他的实例
System.out.println(num1 instanceof String);//false,原因如上
}
}
3.8.6.初始化块
{
this.name = "Kitty";
this.age = 20;
}
- 初始化块只有静态和非静态之分,作用是为成员变量赋初值,类似构造器。初始化块总是先执行(有静态初始化块,则静态先执行),然后是构造器,再者是方法
- 初始化块:构造器中相同的内容可以抽出来放在初始化块中
public class InitTest {
public String name;
public int age;
public int score;
public InitTest(String name) {
this.name = name;
getInform();
}
public InitTest(String name, int age) {
this.name = name;
this.age = age;
getInform();
}
public InitTest(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
getInform();
}
public void getInform() {
System.out.println("初始化块的应用");
}
public static void main(String[] args) {
}
}
getInform()在三个构造器中重复出现,因此可以将其放在初始化块中
{
getInform();
}
3.8.7.组合
class Animal{
public void breath() {
System.out.println("breath");
}
public void beat() {
System.out.println("ppppp");
}
}
/**
* 当我想调用Anmial类中的两个方法,而又不想继承它的时候怎么办呢?
* 可以考虑用组合。方法如下。
*/
public class Combination {
public void breath(Animal a) {
a.breath();
}
public void beat(Animal a) {
a.beat();
}
public static void main(String[] args) {
Combination c = new Combination();
c.beat(new Animal());
c.breath(new Animal());
}
}
4.面向对象的其他内容
4.1.Java增强的包装类
- 与基本数据类型相对应,只不过一个是实列变量,一个是基本变量
- 存在意义,更符合Java的面向对象标准(类)
- 调用Java Arrays类库的sort方法时,如果要改变默认排列,需要将基本类型转换为包装类型
int m = 10;
Integer[] arrays = new Integer[m];
for(int i = 0; i < m; i++) {
arrays[i] = sc.nextInt();
}
Arrays.sort(arrays, new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
if(o1 < o2) return -1;
else return 1;
}
});
for(int x : arrays)
System.out.print(x + " ");
4.2.处理对象
4.2.1.toString()
public String toString(String str) {
return "This is my tostring():" + str;
}
public static void main(String[] args) {
Tostring t = new Tostring();
System.out.println(t.toString("123"));
}
4.2.2.equals()
public boolean equals() {//根据实际情况去重写
return true;
}
public static void main(String[] args) {
Tostring t = new Tostring();
System.out.println(t.equals());
}
tostring()、equals()详情可以参照 https://blog.csdn.net/qq_42017331/article/details/85105442
4.3.类成员
- 类里只能包含成员变量、方法、构造器、初始化块、内部类(包括接口、枚举)。其中static不能修饰构造器
- 类成员属于整个类,而不属于单个对象。
- 类变量既可以通过类访问,也可以通过对象访问。但是通过对象访问类变量只是一种假象,可以这样理解,当通过对象访问类变量时系统会在底层转换为通过该类来访问变量
4.4.final修饰符
- final可以修饰成员变量、方法、类等
- 被final修饰之后,只能赋一次值,或者说被初始化之后就不可以再被更改
4.5.抽象类
- 使用abstract修饰。抽象类顾名思义,有些类只有在使用的时候在知道具体要求,因此可以将此类定义成抽象类,当知道具体要求之后通过继承该类来满足要求
- abstract类里定义的方法必须使用abstract关键字,并且不可以有方法体。可以存在构造器,但是这个构造器是被子类调用的。
- 只要是抽象类就不能创建实例,无论类中是否有抽象方法,因此不能使用new关键字。
- 抽象类中不一定有抽象方法。
- 总结:无具体方法体,让程序更加灵活了
4.6.接口(interface)
4.6.1.接口包含:
- 成员变量(只能是静态常量)、抽象方法、内部类、接口、枚举、私有方法、默认方法、类方法
- 接口只能用public修饰或者省略(默认public)
- 接口中可以有抽象方法、类方法(必须使用static修饰)、默认方法(default关键字)
public interface TestBaseOne {
int num_B= 100;
void getB();
}
public interface TestBaseTow {
int num_A = 10;
void getA();
}
public interface Testor extends TestBaseOne, TestBaseTow{
int num_C = 1000;
void getInform();
void setInform();
default void test() {
System.out.println("这是一个默认的方法");
}
static void statictest() {
System.out.println("这是一个类方法");
}
}
4.6.2.接口的继承
- 接口支持多继承,使用extends关键字,多继承时,接口名中间用”,“隔开
- 类继承接口时使用implement而不是extends,类继承接口之后必须重写接口中的所有抽象方法
- 接口不能显示继承任何类
4.6.3.接口实例
public interface InterTest {
int MAX_SPEED = 200;
void speed(int present);
void price(double price);
void productor(String productor);
//默认方法
default void getInform(char ch) {
System.out.println("最大速度:" + MAX_SPEED + "km/h");
System.out.println("检测信息:" + privateTest(ch));
}
//私有方法,增加默认或类方法实现逻辑
private String privateTest(char ch) {
switch(ch) {
case 'c': return "系统正常 ";
case 'e': return "All systems go";
}
return "error";
}
//类方法
static void staticTest() {
System.out.println("相关测试");
}
}
public class InterTestor implements InterTest{
@Override
public void speed(int present) {
System.out.println("当前速度:" + present + "km/h");
}
@Override
public void price(double price) {
System.out.println("市场价格:" + price +"$");
}
@Override
public void productor(String productor) {
System.out.println("产地:" + productor);
}
public static void main(String[] args) {
InterTest.staticTest();
InterTest t1 = new InterTestor();
t1.getInform('c');
t1.speed(120);
t1.price(1200000);
t1.productor("China");
InterTest t2 = new InterTestor();
t2.getInform('e');
t2.speed(90);
t2.price(100000);
t2.productor("England");
}
}
4.7.内部类
- 定义在另一个类内部的类,包括成员内部类、局部内部类、匿名内部类。成员内部类类似上述所提到的类成员
4.7.1.非静态内部类
- 非静态内部类同普通类没有区别,只不过是定义在一个类内部
- 内部类可以访问到外部类所继承的父类,以及外部类的成员。他们的成员变量通过类名.this区分
- 当内部类成员使用了private等修饰符时,外部类便不能访问到,但外部类成员使用private时,内部类是可以访问到的
- 非静态内部类的成员只在非静态内部类范围内是可知的,不能被外部类直接使用
- 静态成员不能访问非晶态成员的规则在内部类中同样适用
public class Innerclass {
public String name;
class Test{
public int age;
public void getInform() {
System.out.println("hello world");
}
}
public static void main(String[] args) {
}
}
4.7.2.静态内部类
- 使用static修饰,这个内部类属于外部类本身,是外部类的一个静态成员。因此外部类的所有方法、所有初始化块可以使用静态内部类来定义变量,创建对象
Java允许接口中定义内部类,默认使用public static修饰
4.7.3.匿名内部类
- 没有类名,适用于只需要使用一次的类。创建匿名内部类时会立即创建一个类实例
- 其实现接口或者是父类(实参列表)。因此匿名内部类必须实现一个接口或者继承一个父类
- 匿名内部类中无构造器
Arrays.sort(arrays, new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
if(o1 < o2) return -1;
else return 1;
}
});
4.8.枚举
- 实例有限且固定的类
- 需要通过private隐藏构造器
- 所有可能实例都使用public static final修饰
- 可以提供静态方法,允许其他程序根据特定参数来获取与之匹配的实例
- 使用enum关键字。并且所有的实例必须在第一行显示列出,中间用”,“隔开
switch(也可以是枚举值)
public class Test {
public void getValues(Season e) {
switch(e) {
case Spring : System.out.println(1);break;
case Summer : System.out.println(2);break;
case Autumn : System.out.println(3);break;
case Winter : System.out.println(4);break;
}
}
public static void main(String[] args) {
for(Season s : Season.values()) {
System.out.println(s);
}
}
}