Java基础语法(上)
Java简介
Java是一门程序开发语言. 1991年由sun公司的James Gosling和他的团队一起开发了一个叫Oak的语言. 在1995年更名为Java. 一直沿用至今.
Java是目前全世界使用人数最多的编程语言. Toibe 排行榜第一. https://www.tiobe.com/tiobe-index/
丰富的开源社区和非常多的开源框架.
国内各大一线公司都在使用Java.
特点:
- 简单: 针对C++简化了很多
Java相关概念:
JVM(Java Virtual Machine): java虚拟机, 用来模拟统一的硬件平台环境, 供java程序运行的 一个软件
JRE(Java Runtime Environment): java运行时环境. 里面包含了JVM和一些java运行时的类库
JDK(Java Development Kit): java开发包. 包含JRE和java开发工具包.
第一个Java程序
首先, 我们在c盘下创建一个文件夹. 叫test. 然后在test文件夹中.创建一个文本文档. 起名为first.java
写入以下代码
public class first{
public static void main(String[] args){
System.out.println("你好 终于写了一个程序了.");
}
} 使用命令javac对我们的程序进行编译
使用命令javac对我们的程序进行编译
注意: javac命令后面跟的是文件名
java命令后面跟的是类名. 也就是我们代码中public class 后面的那个名字
接下来. 我们对程序进行详解:
public class first{ ------> 这一行表示创建一个类. 类是java程序运行的最小单元. 必须要有类
public static void main(String[] args){ -----> java程序的入口. 一切从这里开始执行
System.out.println("你好 终于写了一个程序了."); ---> 让程序打印一句话, 内容是引号中的内容
} ---> 对应程序入口的结束
} --> 对应类的结束 Java中的注释
一. 单行注释
// 单行注释. 这一行内容会被jvm运行的时候过滤掉.
二. 多行注释
/* 多行注释 一次注释多行代码 */
三. 文档注释
/** * 文档注释 * 后期可以使用javadoc命令生成api文档 */
常用的是单行注释 // 和 文档注释 /*** /
一般在如下情况可以添加代码注释:
- 核心的解决方案
- 比较难懂的业务逻辑
- 记录代码的存在经历
变量
java中的变量:
数据类型 变量名 = 值;
本节, 我们只介绍一些最最常用的基本数据类型. 后面的进阶我们会进一步详细的介绍数据类型.
int
int主要表示的就是我们生活中使用的整数. 比如, 1, 10086等等.
int类型可以执行的操作: 加减乘除等. + - /
int a = 20; int b = 10; int c = a + b; System.out.println(“a + b = “ + c); int d = a - b; System.out.println(“a - b = “ + d); int e = a b; System.out.println(“a b = “ + e); int f = a / b; System.out.println(“a / b = “ + f);
double
double表示的是小数. 比如你去菜市场买个黄瓜花费了1.25元. 这就是小数. double类型的数据可以执行的操作和int基本相同. 不同的是. 计算结果一定是小数
double a = 1.88; double b = 1.75; double c = a + b; System.out.println(“a + b = “ + c); double d = a - b; System.out.println(“a - b = “ + d); double e = a b; System.out.println(“a * b = “ + e); double f = a / b; System.out.println(“a / b = “ + f);
String 字符串
String表示的是字符串. 主要是针对文字进行描述的. 这里要注意的是字符串(String) 的S必须大写
String s = “近日, 三胖又要制造超大号窜天猴了”; // 双引号括起来的内容就是字符串 System.out.println(“s = “ + s);
字符串可以进行加法运算. 表示字符串的拼接.
String s1 = “AAA”; String s2 = “BBB”; String s3 = s1 + s2; System.out.println(s3); String s4 = s3 + “, oh, yeah!”; System.out.println(s4);
boolean 布尔
boolean主要表示的是真或者假. 翻译过来就是 对和错. 真命题, 假命题
boolean a = true; boolean b = false; System.out.println(a); System.out.println(b);
boolean c = 1 > 2; boolean d = 2 > 1; System.out.println(c); System.out.println(d); int e = 10; // = 表示赋值 System.out.println(e == 10); // 判断是否相等要用 == System.out.println(e != 10);
```java // boolean值是用来判断条件的
变量的简单应用
int meals = 100+200+120+40; // 餐费
int traffic = 10 * 22; // 交通费
int clothing = 200+400+150; // 服装费
int all = meals + traffic + clothing; //总和
System.out.println("一共花费:" + all); // 一共花费:1430 用户输入
在java中使用输入功能需要使用Scanner类来完成.
import java.util.Scanner; // 使用Scanner必须要导入这个包. 关于导包后面会详解. 暂时先这么写
public class TestIf {
public static void main(String[] args) {
// 准备一个Scanner对象
Scanner sc = new Scanner(System.in);
}
} 具体操作
// 获取到用户输入的内容
Scanner sc = new Scanner(System.in);
// 你想要什么样的数据?
// 常用的有
// 获取到int类型的数据
int i = sc.nextInt();
System.out.println("i = " + i);
// 获取到double类型的数据
double d = sc.nextDouble();
System.out.println("d = " + d);
// 获取到字符串. 以回车为结尾
String line = sc.nextLine();
System.out.println("line = " + line); 应用: 计算这个月的零花钱
Scanner sc = new Scanner(System.in);
// 提示
System.out.println("请输入您的工资:");
// 接收工资
double salary = sc.nextDouble();
// 显示工资
System.out.println("工资是:" + salary);
// 计算零花钱
double pin = salary * (1-0.95);
// 显示零花钱
System.out.println("零花钱:" + pin); If语句
Scanner sc = new Scanner(System.in);
System.out.println("请输入你一个月多少零花钱:");
double pin = sc.nextDouble();
if(pin > 500){
System.out.println("洗脚城走一波");
} else {
System.out.println("捡一块砖头自己回家蹭");
}
System.out.println("happy"); // 输入考试分数
Scanner sc = new Scanner(System.in);
int score = sc.nextInt();
if(score >= 100){
System.out.println("优秀");
} else if (score >= 80 ){
System.out.println("良好");
} else if (score >= 70 ){
System.out.println("中等");
} else if (score >= 60 ){
System.out.println("及格");
} else {
System.out.println("不及格");
} While语句
System.out.println("1. 登录");
System.out.println("2. 找个怪多的地方");
int i = 0;
while(i < 5){
System.out.println("3. F1~ 来自东方的神秘力量.");
System.out.println("4. 换个地方继续.");
i = i + 1;
}
System.out.println("5. 没意思, 走了~"); 方法
- 写一个试试一个能从1数到100的方法, 并调用
public class TestMethod {
public static void count100(){
for(int i = 1; i <= 100; i++){
System.out.println(i);
}
}
public static void main(String[] args) {
count100();
}
} - 方法的重载 (方法的名字相同, 参数的个数或类型不同)
public class TestMethod {
public static int add(int a, int b){
System.out.println("两个int");
return a + b;
}
public static long add(int a, long b){
System.out.println("一个int, 一个long");
return a + b;
}
public static double add(int a, double b){
System.out.println("一个int, 一个double");
return a + b;
}
public static void main(String[] args) {
System.out.println(add(10, 20));
System.out.println(add(10, 20L));
System.out.println(add(10, 1.25));
}
} 面向对象
- 用面向对象的思维来完成植物大战僵尸
public class Plant {
String name;
int attack;
int hp;
public Plant(String name, int attack, int hp){
this.name = name;
this.attack = attack;
this.hp = hp;
}
public void fight(Zombie zombie){
System.out.println(this.name + "正在攻击:" + zombie.name);
zombie.hp -= this.attack;
System.out.println(zombie.name+"还剩下"+zombie.hp+"血量");
}
} public class Zombie {
String name;
int attack;
int hp;
public Zombie(String name, int attack, int hp){
this.name = name;
this.attack = attack;
this.hp = hp;
}
public void fight(Plant plant){
System.out.println(this.name + "正在攻击:" + plant.name);
plant.hp -= this.attack;
System.out.println(plant.name+"还剩下"+plant.hp+"血量");
}
} public class Client {
public static void main(String[] args) {
Plant p1 = new Plant("豌豆荚", 10, 100);
Zombie zb = new Zombie("铁通僵尸", 20, 300);
p1.fight(zb);
p1.fight(zb);
p1.fight(zb);
p1.fight(zb);
p1.fight(zb);
zb.fight(p1);
}
} 静态变量 (被static修饰的变量会被所有的对象共享, 并且, 在内存里只会保留一份)
public class Person{
String name;
String address;
static String country = "大清";
public Person(String name, String address){
this.name = name;
this.address = address;
}
public static void main(String[] args){
Person p1 = new Person("李大猛", "北京八大胡同");
Person p2 = new Person("花花", "北京朝阳");
p1.country = "民国";
System.out.println(p1.country);
System.out.println(p2.country); // 民国
}
} 静态方法
public class Person{
public static void huo(){
System.out.println("是人都想火");
}
public static void main(String[] args){
huo(); // 由于是自己类. 可以直接访问静态方法
Person.huo();// 最好呢, 还是用类名去访问.
}
} 在创建对象的时候, 首先加载的是静态的内容, 然后才是非静态内容.
在静态方法里, 不能使用this.
也不能直接调用自己类中的其他成员(方法, 变量). 但是反过来是可以的.
重点: 静态的东西不属于对象, 直接属于类, 优先于对象产生. 使用的时候使用类名去访问.
访问权限
| 释义 | 自己类 | 自己包 | 其他包 | |
|---|---|---|---|---|
| public | 公共的 | OK | OK | OK |
| default | 默认的 | OK | OK | NO |
| private | 私有的 | OK | NO | NO |
package com.dylan.bao;
public class Person {
String def = "def"; // 默认啥都不写就是包访问权限
public String pub = "pub"; // 公共的
private String pri = "pri"; // 自己的
public static void main(String[] args) {
Person p = new Person();
// 自己类里,都没问题
System.out.println(p.def);
System.out.println(p.pub);
System.out.println(p.pri);
}
} 自己包里的其他类试试
package com.dylan.bao;
public class TestPackagePerson {
public static void main(String[] args) {
Person p = new Person();
// 自己包里. private不行了
System.out.println(p.def);
System.out.println(p.pub);
// System.out.println(p.pri); // 报错了
}
} 一般情况, 我们很少用包访问权限. 这种权限并不舒服. 说白了. 你家里的东西要么是都能让人看的, 要么就是自己用的. 很少会专门准备一些东西给你的邻居用的. 程序也一样. 很少会用默认的访问权限.
getter and setter
package com.xyq.bao;
public class Person {
private String name;
private int age;
// 设置名字
public void setName(String name){
this.name = name;
}
// 获取名字
public String getName() {
return name;
}
// 获取年龄
public int getAge() {
return age;
}
// 设置年龄
public void setAge(int age){
if(age < 0){
this.age = 0;
} else {
this.age = age;
}
}
public void chi(){
System.out.println(this.name+"在吃东西");
}
} IDEA软件中, 快捷键: 空白处, 右键-> generate -> getter and setter -> ctrl + A -> OK ! enjoy
~
继承
写个妖怪
package com.dylan.bao;
public class YaoGuai {
private void paSi(){
System.out.println("妖怪都怕死");
}
public void chiRen(){
System.out.println("妖怪喜欢吃人");
}
} 写个黑熊
package com.dylan.bao;
public class HeiXiong extends YaoGuai {
} 测试一下
package com.dylan.bao;
public class TestExtends {
public static void main(String[] args) {
HeiXiong hx = new HeiXiong();
hx.chiRen();
// hx.paSi(); //报错, 找不到怕死
}
} 所以从另一个角度讲, 子类其实是对父类进行了扩展. 在父类已经给了一些方法和属性的基础上再加一点儿新功能. 可以节省很多的代码.
注意: java只能单继承. 说白了. 每个儿子只能有一个爹
多态
package com.dylan.bao;
public class Animal{
public void eat(){
System.out.println("动物吃东西");
}
} package com.dylan.bao;
public class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
} package com.dylan.bao;
public class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
} 把子类的对象赋值给父类的变量. 这个在java里被称为向上转型.
向上转型的优点: 自动转型. 把不相关的东西转化成相同的数据类型. 猫, 狗, 鹦鹉都当成动物来看~~
package com.dylan.bao;
public class Person{
public void feed(Animal ani){
ani.eat();
}
} package com.dylan.bao;
public class Test {
public static void main(String[] args) {
Person p = new Person();
Animal c = new Cat();
Animal d = new Dog();
p.feed(c);
f.feed(d);
}
} 多态的三个要素:
要有继承关系
要重写
要向上转型
优点: 让程序有超强的可扩展性.
如果你想把父类的变量转化回子类的类型. 就必须要强转
(转化之后的类型) 变量
public static void main(String[] args){
Animal ani = new Cat(); //向上转型
Cat c = (Cat) ani;//必须要强转
} final关键字
被final修饰的变量: 不可以被重新赋值, 又被称为常量.
被final修饰的方法: 不可以被重写
被final修饰的类: 不可以被继承
package com.dylan.bao;
public final class Diamonds {
private final int weight = 100;
public void change(){
this.weight = 200; // 报错. 被final修饰. 不可以被修改
}
public final void bling(){
System.out.println("钻石是不灵不灵的");
}
} package com.dylan.bao;
public class PinkDiamonds extends Diamonds {
public void bling(){ // 被final修饰的方法不可以被重写
System.out.println("钻石是不灵不灵的");
}
} 抽象类
package com.dylan.bao;
public abstract class Animal { // 含有抽象方法的类必须是抽象类
public abstract void chi(); // 抽象方法
public void dong(){ // 抽象类也可以有正常的方法
System.out.println("估拥");
}
} package com.dylan.bao;
public class Cat extends Animal{ // 继承抽象类, 必须重写抽象方法
public void chi(){ // 猫是有确定的吃的方式的.
System.out.println("猫吃鱼");
}
} 这样间接的. 我们使用抽象类就对子类进行了约束. 要求子类必须有一个xxx方法.
接口
接口其实就是一种特殊的抽象类. 接口里所有的方法都是抽象方法.
package com.dylan.bao;
/**
* 注意: 这里不能写class. 要写interface
*/
public interface Valuable {
void sell(); // 由于接口里所有的方法都是public abstract 所以不放修饰符. 默认是全局抽象
} 接口既然全都是抽象方法, 那如何使用呢? 和抽象类一样. 也要借助于子类. 但是, 接口终归是接口, 这玩意不是类. 所以, 记住
继承接口的只能是接口.
那接口和类之间怎么产生关系呢?
类可以实现接口(implements), 实现和继承其实从语义上讲是一样的.
比如, 熊猫是一种值钱的东西
package com.dylan.bao;
// 类实现接口. 类继承类. 接口继承接口.
public class Panda implements Valuable {
@Override // 重写
public void sell() {
System.out.println("熊猫可以卖个好价钱");
}
} 类与类之间: 继承关系
接口和接口: 继承关系
类和接口: 实现关系
在这里. 我们把panda称之为Valuable的一个实现类, 接口和接口实现类之间其实就是一种另类的继承关系. 接口的实现类必须实现(重写)接口中所有的抽象方法. 否则这个类必须是一个抽象类. 接口也可以对类进行约束.
用抽象类不也挺好的么. 为什么非要搞出一个接口?
java中一个类只能有一个父类. 这就导致一个问题. 说, 熊猫是一种值钱的东西. 熊猫继承值钱的东西. 但是, 熊猫还是一个受保护的东西啊. 熊猫再继承受保护的东西. 那就不对了. java是单继承啊. 语法上不让你这么写. 怎么办? 接口可以多实现
~
package com.dylan.bao;
public class Panda extends Animal implements Valuable, Protectable {
@Override
public void sell() {
System.out.println("熊猫可以卖个好价钱");
}
@Override
public void protect() {
System.out.println("熊猫应该被保护起来");
}
@Override
public void chi() {
System.out.println("熊猫吃竹子");
}
} package com.xyq.bao;
public class Test {
public static void main(String[] args) {
Animal ani = new Panda();
ani.chi();
Valuable val = new Panda();
val.sell();
Protectable pro = new Panda();
pro.protect();
Panda pan = new Panda();
pan.chi();
pan.protect();
pan.sell();
}
} 一个类可以实现多个无关的接口
一个接口可以被多个无关的类实现
接口最重要的作用: 把不想关的两个物体连接起来. 通过接口连接.
接口里都是方法么? 不, 接口里也有变量, 但是接口里的变量全部都是全局静态常量.
public interface Valuable{
double money = 100; // 相当于 public static final double money = 100;
}
public class Client{
public static void main(String[] args){
System.out.println(Valuable.money); //可以使用类名直接调用. 静态的
Valuable.money = 200; // 报错. 不可以被修改
}
} 注意: 我们很少会在接口里设置变量. 更多的是使用接口来统一数据类型. 和对实现类进行约束.
equals 和 ==
package com.dylan.bao;
public class Cat {
private String name;
private String color;
public Cat(String name, String color) {
this.name = name;
this.color = color;
}
public static void main(String[] args) {
Cat c1 = new Cat("小花", "红色");
Cat c2 = new Cat("小花", "红色");
System.out.println(c1 == c2); //false
System.out.println(c1.equals(c2)); //false
}
} == 判断的是两只猫是不是同一只猫. 判断内存地址
equals我们调用的是object里的equals, 和==没有区别
package com.dylan.bao;
public class Cat {
private String name;
private String color;
public Cat(String name, String color) {
this.name = name;
this.color = color;
}
// 手动给出equals方法
public boolean equals(Cat c){
if(this.name == c.name && this.color == c.color){
return true;
} else {
return false;
}
}
public static void main(String[] args) {
Cat c1 = new Cat("小花", "红色");
Cat c2 = new Cat("小花", "红色");
System.out.println(c1 == c2); //false
System.out.println(c1.equals(c2)); //true
}
} 搞定. 我们通过==来判断两只猫是否是同一只猫. 通过equals来判断两只猫长的是不是一样.
接下来, 看一个玄学问题
package com.dylan.bao;
public class Test {
public static void main(String[] args) {
String a1 = "竹鼠";
String a2 = "竹鼠";
System.out.println(a1 == a2); // true
System.out.println(a1.equals(a2)); // true
String a3 = new String("节奏狗");
String a4 = new String("节奏狗");
System.out.println(a3 == a4); // false
System.out.println(a3.equals(a4)); // true
}
} 为什么会这样. 因为字符串是我们使用频率最高的一种数据类型. java会自动帮我们对字符串进行缓存. 发现一样的字符串了就不再创建新的了. 所以a1和a2内存地址是一样的. 所以两个都是真. a3在创建的时候new了一次. a4也new了一次. 此时, “节奏狗” 三个字被缓存. 但是. new的时候是要创建对象的. 对象再引入”节奏狗”三个字. 所以. 两个对象的地址是不一样的. 但是内容是一样的.
综上, 我们在判断两个字符串是否一致的时候, 一定要用equals 这样就是很稳定的判断内容是否一样.
toString()
package com.dylan.bao;
public class Cat {
private String name;
private String color;
public Cat(String name, String color) {
this.name = name;
this.color = color;
}
public String toString(){
return "一只"+this.color+"猫, 名字是:"+this.name;
}
public static void main(String[] args) {
Cat c = new Cat("韩梅梅", "绿色");
System.out.println(c); // 一只绿***, 名字是:韩梅梅
}
} instanceof
package com.xyq.bao;
public class Test {
public static void main(String[] args) {
Animal a = new Cat();
if(a instanceof Cat){
System.out.println("这个动物是一只猫");
} else {
System.out.println("这个动物不是一只猫");
}
}
} 内存分析
package com.xyq.bao;
public class Person {
private String name;
private int age;
private String address;
public static int num = 0;
public Person(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
num++;
}
public static void main(String[] args) {
Person p1 = new Person("少林寺", 18, "河南嵩山");
Person p2 = new Person("吐鲁番", 12, "新疆");
Person p3 = new Person("海南岛", 16, "海南");
Person p4 = new Person("北戴河", 4, "河北");
System.out.println(Person.num);
}
} 在java中一共会分为4块内存区域. 分别是: 堆, 栈, 代码区, 数据区.
堆: 放对象. new的东西都在这里
栈: 局部变量. 基础数据类型变量.
代码区: 类.
数据区: 常量池, 静态变量.
常量池: 我们前面讲equals的时候. 说过java会帮我们缓存一些数据. 这些数据就放在常量池里
接下来.我们先分析第一句话
Person p1 = new Person(“少林寺”, 18, “河南嵩山”);
其余的同理
参数传递
基本数据类型是值传递
package com.xyq.bao;
public class TestMethod {
public static void change(String b){
b = "aaa";
int hashCode = System.identityHashCode(b);
System.out.println(hashCode); //257895351
}
public static void main(String[] args) {
String a = "bbb";
change(a);
System.out.println(a); // 10
int hashCode = System.identityHashCode(a); // 查看到虚拟机映射的地址 HASHCODE
System.out.println(hashCode); // 1929600551
}
} 对象是引用传递
public class Temp {
public static void change(Person p){
p.setName("ABC");
System.out.println(p); // Person@f5f2bb7
int hashCode = System.identityHashCode(p); // 查看到虚拟机映射的地址 HASHCODE
System.out.println(hashCode); // 257895351
}
public static void main(String[] args) {
Person p = new Person("小明", "male");
change(p);
System.out.println(p.name); // ABC
int hashCode = System.identityHashCode(p); // 查看到虚拟机映射的地址 HASHCODE
System.out.println(p); // Person@f5f2bb7
System.out.println(hashCode); // 257895351
}
} 异常处理
异常类的根: Throwable
两个分支: Error和Exception
Exception又分为RuntimeException和其他Exception
RuntimeException表示运行时异常. 只有跑起来才知道错了.
其他Exception: 不用跑就知道错了
Error: 系统级错误. 程序员一般不好处理.
try ... catch
在idea里可以ctrl+alt+t快速的给代码加上try…catch
package com.dylan.bao;
public class CreateException {
public static void main(String[] args) {
try {
System.out.println(1/0);
} catch (ArithmeticException e) {
System.out.println("出现错误, 请联系系统管理员");
}
}
} throws和throw
public class Test {
public static void chu(int a, int b) throws Exception{ //告诉外面, 我要扔出来一个错误
if (b==0){ // 0不能做除数
// 主动抛异常
throw new Exception("你不可以给我一个0"); // 真正的向外抛出一个异常
} else {
System.out.println(a/b);
}
}
public static void main(String[] args) {
try {
chu(1, 2);
} catch (Exception e) {
e.printStackTrace();
// System.out.println(e.getMassage());
}
}
} 如果方法中主动向外抛异常, 那么这个方法必须要通知外界去处理异常, 也就是说, 方法内部有throw, 方法的声明就一定有throws. 反之则不一定.
自定义异常
模拟男女澡堂子, 女方不能进男澡堂
public class Person {
String name;
String gender;
public Person(String name, String gender) {
this.name = name;
this.gender = gender;
}
} public class Zaotangzi {
public void male(Person p) throws GenderException {
if(p.gender.equals("男")){
System.out.println("Welcome!");
}
else{
throw new GenderException("性别不对, 这里是男澡堂子!");
}
}
} public class GenderException extends Exception{
public GenderException(String msg){
super(msg);
}
} public class Test {
public static void main(String[] args) throws GenderException {
Person p = new Person("小明", "女");
Zaotangzi z = new Zaotangzi();
z.male(p);
}
} 
京公网安备 11010502036488号