/*
* 引用传递
* 参数之间的传递
*/
class Ref1 {
int temp = 10;
}
public class RefDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Ref1 r1 = new Ref1();
r1.temp = 20;
System.out.println(r1.temp);
tell(r1);
System.out.println(r1.temp);
}
public static void tell(Ref1 r2) {
r2.temp = 30;
}
}
/*
* 引用传递
* String 类型的不可变性
* String 类型里面的数据是不能被更改的
*/
public class RefDemo2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
String str1 = "Hello";
System.out.println(str1);
tell(str1);
System.out.println(str1);
}
public static void tell(String str2) {
str2 = "World";
}
}
/*
* 引用传递
* String类型被更改,实质是因为重新分配了内存
*/
class Ref2{
String str1 = "Hello";
}
public class RefDemo3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Ref2 r1 = new Ref2();
r1.str1 = "World";
System.out.println(r1.str1);
tell(r1);
System.out.println(r1.str1);
}
public static void tell(Ref2 r2) {
r2.str1 = "王圣贤";
}
}
图片说明
11.2 this关键字
表示类中属性和调用方法
调用本类中的构造方法
表示当前对象
实例
/*
* this 的作用:
* 表示本类的属性或方法(上一个Demo介绍)
* 调用本类中的构造方法(上一个Demo介绍)
* 表示当前对象
*/
class People1{
public void tell() {
System.out.println(this);
}
}
public class ThisDemo2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
People1 per = new People1();
System.out.println(per);
per.tell();
}
}
/*
* final修饰的类无法被继承
* final修饰的方法不能被重写
* final修饰的变量为常量,且无法被修改
*/
class People { //final修饰的类无法被继承
public void tell() { //final修饰的方法不能被重写
}
}
class Student extends People {
public void tell() {
}
}
public class FinalDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
final String name = "张三"; //final修饰的变量为常量,且无法被修改
System.out.println(name);
}
}
12.2 Java抽象类
抽象类:包含一个抽象方法的类为抽象类
抽象方法:声明而未被实现的方法,抽象方法必须使用abstract关键字声明;
抽象类可以被子类继承,但子类必须重写抽象类中所有的抽象方法;
格式:
abstract class className {
属性;
方法;
抽象方法;
}
抽象类不能直接实例化,需要通过子类实例化;
实例:
/*
* 抽象类:包含一个抽象方法的类
* 抽象方法:未被实现的方法
* 抽象类被子类继承,则子类必须重写抽象类的所有抽象方法
* 抽象类不能直接实例化,需要通过子类实例化
*/
abstract class Abs { //抽象类:包含一个抽象方法的类
private int age;
public void tell () {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void say(); //抽象方法:未被实现的方法
}
class Abs1 extends Abs{ //抽象类被子类继承,则子类必须重写抽象类的所有抽象方法
public void say() {
System.out.println(getAge());
}
}
public class AbsDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//Abs abs = new Abs(); //抽象类不能直接实例化,需要通过子类实例化
Abs1 a = new Abs1();
a.setAge(20);
a.say();
a.tell();
}
}
/*
* 接口:由全局变量和公共抽象方法组成
* 接口的实现必须通过子类,使用关键字implements, 而且可以多实现
* 一个子类可以同时继承抽象类和接口
*/
interface inter {
public static final int ACG = 100; //全局变量:全局的,不可改变的
public abstract void tell();
}
interface inter2 {
public abstract void say();
}
interface inter3 extends inter, inter2 {
}
abstract class Abs2 {
public abstract void print();
}
class A extends Abs2 implements inter, inter2 {
public void tell() {
}
public void say() {
}
public void print() {
}
}
public class interDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//inter I = new inter();
A a = new A();
a.tell();
a.say();
a.print();
System.out.println(inter.ACG);
}
}
13 字符串
13.1 String字符串
实例化String对象的两种方式;
直接赋值;
使用关键字new;
比较两个字符串是否相等
不可以用“==”,因为这会比较两个字符串的地址;
用“equals”用于比较两个字符串的内容;
实例:
/*
* String实例化对象有两个方法:直接赋值,使用new关键字
* String 不可更改性
*/
public class StringDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
String str = "Hello";
String str2 = new String("Hello"); //用new关键字,会创建两个地址
System.out.println(str == str2); //"=="用于比较两个地址
System.out.println(str.equals(str2)); //"equals"用于比较内容
}
}
图片说明:
13.2 String字符串常用方法
长度:length();
字符串转化为数组:toCharArray();
从字符串中取出指定位置的字符:charAt();
字符串与byte数据的转换:getByte();
过滤字符串中存在的字符:indexOf();如果有,则返回当前字符的位置;若无,则返回false;
去掉字符串的前后空格:trim();
从字符串中取出子字符串:subString();
大小写转换:toLower();toUpperCase();
判断字符串的开头结尾字符:endsWith();startWith();
替换String字符串中的一个字符:replace();
实例:
/*
* String的常用方法
*/
public class StringDemo2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
String str = " asjfsldfjasfsfs";
//length()方法
System.out.println(str.length());
//toCharArray()方法
char c[] = str.toCharArray();
for(int i = 0 ; i < c.length; i++) {
System.out.print(c[i] +" ");
}
System.out.println();
//charAt()方法
System.out.println(str.charAt(7));
//getBytes()方法
byte[] b = str.getBytes();
for(int i = 0 ; i < b.length; i++) {
System.out.print(b[i] +" ");
}
System.out.println();
//indexOf()方法
System.out.println("f的位置为"+str.indexOf("f"));
//trim()方法
System.out.println(str.trim());
}
}
/*
* 认识泛型:
* 1.示例:经纬度:int, float, double
* 2.泛型可以解决数据的安全性问题,可以定义希望的类型。
* 3.定义: class Point<T>; Point<String> p = new Point<String>();
*
*/
class Point<T> {
private T x;
private T y;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
public class GenericDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Point<String> p = new Point<String>();
p.setX("精度为:100");
p.setY("纬度为:120");
System.out.println("X=" + p.getX() + " Y=" + p.getY());
}
}
15.2 在构造方法中使用泛型
构造方法:可以为类中属性初始化;
若类中属性通过泛型指定,构造方法不变;
实例:
/*
* 构造方法中使用泛型
* 注意:构造方法中使用泛型,并没有发生变化
*/
class Test <T> { //不能用Test作为类名,未写入类文件。项目可能不一致,如果出现这种情况,则尝试刷新此项目并构建它
private T value;
public Test(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class GenericDemo2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Test<String> c = new Test<String>("泛型中使用构造方法");
System.out.println(c.getValue());
}
}
15.3 设置多个泛型
设置多个泛型直接在<>中添加多个泛型就可以了;
定义:class 类名<泛型,泛型> {
- [ ] 实例:
/*
* 设置多个泛型
*/
class Gen<K,T> {
private K key;
private T take;
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public T getTake() {
return take;
}
public void setTake(T take) {
this.take = take;
}
}
public class GenericDemo3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Gen<String, Integer> gen = new Gen<String, Integer>(); //Integer,而非int
gen.setKey("hello, ");
gen.setTake(9527);
System.out.println(gen.getKey() + gen.getTake());
}
}
15.4 泛型:通配符:?
通配符
可用在主类中的非主方法中,表示未知的类型;
实例:
在这里插入代码片
15.5 泛型接口
在JDK 1.5中,不仅可以声明泛型类,还可以声明泛型接口;
声明泛型接口类似于声明泛型类;
格式:interface 接口名<泛型> {}
- [ ] 实例:
class Info<T> {
public T key;
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
//通过该方法,可以将地址转化为内容
public String toString() {
return this.getKey().toString();
}
}
public class GenericDemo4 {
public static void main(String[] args) {
Info<String> i = new Info<String>();
i.setKey("Hello, world");
tell(i);
}
/*
* 通配符:无论什么类型,都可以被执行
*/
public static void tell(Info<?> b) {
System.out.println(b); //通过toString(),将地址转化为了内容
}
}
15.6 泛型方法
泛型方法中可以定义泛型参数,此时,泛型参数的类型就是传输数据类型;
格式:
访问权限 <泛型标识> 泛型标识 方法名称([泛型标识], [参数名称])
如 : public <T> T tell(T t) {};
实例:
/*
* 泛型方法
* 定义: public <T> T tell(T t);
*/
class Gene{
public <T>T tell(T t) {
return t;
}
}
public class GenericDemo6 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Gene g = new Gene();
String str = g.tell("sfdsfsd");
System.out.println(str);
int num = g.tell(42343);
System.out.println(num);
}
}
15.7 泛型数组
在使用泛型方法时,也可以传递或返回一个泛型数组;
实例:
/*
* 定义一个泛型数组
*
*/
public class GenericDemo7 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
String str[] = {"fefs", "fsdf", "serwe"};
tell(str);
}
public static <T> void tell(T arr[]) {
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
16 多线程编程
16.1 线程与进程
线程:程序中单独顺序的控制流
线程本身依靠程序运行;线程是程序中的顺序控制流,只能使用分配给程序的资源与环境;
进程:执行中的程序
一个进程可含多个线程;至少有一个线程;
单线程:主方法就是一个主线程;
多线程:一个程序运行多个任务;更合理的使用CPU;
16.2 线程的实现
线程的两种实现方式:
继承Thread类
和实现Runnable接口
Thread 类
在java.lang中定义,继承Thread类,必须重写run()方法;
定义格式:
class className extends Thread {
run() { };
}
实例:
public class MyThread extends Thread{
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for(int i = 0; i < 10; i++) {
System.out.println(this.name + i + " ");
}
super.run();
}
}
/*
* 线程的实现
* 1.通过使用Thread类实现
* 2.通过使用Runnable接口实现
*/
public class ThreadDemo {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThread t1 = new MyThread("A");
MyThread t2 = new MyThread("B");
//线程的执行一定不是在主方法中调用run()执行的,这样不会并发执行
// t1.run();
// t2.run();
//通过start()才可以并发执行;
t1.start();
t2.start();
}
}
public class MyRunnable implements Runnable{
private String name;
public MyRunnable(String name) {
this.name = name;
}
public void run() {
for(int i = 0; i < 10; i++) {
System.out.println(this.name + i);
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyRunnable mr1 = new MyRunnable("A");
MyRunnable mr2 = new MyRunnable("B");
//由于Runnable中没有类似start()的方法,因此还是需要调用Thread来实现
Thread t1 = new Thread(mr1);
Thread t2 = new Thread (mr2);
t1.start();
t2.start();
}
}
16.3 线程的状态
线程状态:
创建线程:准备好一个多线程的对象;
就绪状态:调用了start()方法,等待CPU进行调度;
运行状态:执行了run()方法;
阻塞状态:暂时停止执行,可能将资源交给了其他线程;
终止(死亡)状态:线程销毁
实例:
/*
* 线程的五个方法
* 1.getName(); currentThread(); isAlive(); join(); sleep(); yield();
* join(), 强行运行
* isAlive(),是否已经开始运行
* sleep(),休眠,通过Thread.sleep()调用;
* yield(),礼让
*/
class RunnableDemo implements Runnable {
private String name;
public RunnableDemo (String name) {
this.name = name;
}
public void run() {
for (int i = 0; i < 10; i++) {
if(i == 5) {
System.out.println("礼让");
Thread.yield();
}
try {
Thread.sleep(1000); //线程的休眠
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//currentThread()方法,与currentThread().getName()方法。
System.out.println("当前线程对象" + Thread.currentThread() + " "
+"线程名称"+ Thread.currentThread().getName() +" " + i);
}
}
}
public class ThreadDemo3 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
RunnableDemo rd = new RunnableDemo("A");
RunnableDemo rd2 = new RunnableDemo("B");
Thread t1 = new Thread(rd);
Thread t2 = new Thread(rd2);
//isAlive()方法
System.out.println(t1.isAlive());
t1.start();
t2.start();
System.out.println(t1.isAlive());
System.out.println();System.out.println();System.out.println();
for (int i = 0 ; i < 20; i++) {
if(i > 10) {
try {
//join(),强行运行
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
}
}
}
16.4 线程的常用方法
取得线程名称:getName();
取得当前线程对象:currentThread();
判断线程是否启动:isAlive();
现成的强行运行:join();
线程的休眠:sleep();
16.5 线程的优先级
优先级顺序设置
1-MIN_PRIORITY;
10-MAX_PRIORITY;
5-NORM_PRIORITY;
实例
/*
* 线程优先级的概念
* 1.Thread.MAXPRIORITY , Thread.MINPRIORITY, Thread.NORMPRIORITY
* 2.优先级只是一个可能性,更有可能抢到CPU资源
*/
class Thread4 extends Thread {
public void run() {
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " " + i);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
public class ThreadDemo4 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Thread t1 = new Thread(new Thread4(), "A");
Thread t2 = new Thread(new Thread4(), "B");
Thread t3 = new Thread(new Thread4(), "C");
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t3.setPriority(Thread.NORM_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
16.6 同步与死锁
同步代码块:在代码块中加入“synchronized”,则此代码块为同步代码块;
同步代码块格式:synchronized (同步对象) {需要同步的代码块};
同步方法:除代码块可以同步,方法也可以同步;
synchronized void 方法名称 {}
死锁:例如,刚毕业的学生期望高薪工作,而公司需要有经验的员工;
实例:
/*
* synchronized关键字
* 1.同步代码块
* 2.同步方法
*/
class MyThreadDemo implements Runnable{
private int ticket = 5;
public void run() {
for(int i = 0; i< 10; i++) {
tell();
//同步代码块
// synchronized(this) {
//
// }
}
}
//同步方法
public synchronized void tell() {
if(ticket > 0) {
try {
Thread.sleep(500);
System.out.println("ticket:" + ticket--);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
/*
* 死锁:学生找高薪,公司要求有经验
*
*/
public class ThreadDemo5 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
MyThreadDemo t = new MyThreadDemo();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
t1.start();
t2.start();
t3.start();
}
}