foojay.io Open in urlscan Pro
2606:4700::6812:1eaf  Public Scan

Submitted URL: https://go.jetbrains.com/NDI2LVFWRC0xMTQAAAGHPLP_lIb6fS611paa3L-C74j6yPgYDGMBrdXDj3MZOtPJlBC6cwtAn2O14zdReAI4xeX6Ofs=
Effective URL: https://foojay.io/today/use-pattern-matching-to-simplify-java/?mkt_tok=NDI2LVFWRC0xMTQAAAGHPLP_lNiFSLBApIVMT0rhNUF...
Submission: On October 06 via api from BE — Scanned from DE

Form analysis 3 forms found in the DOM

GET https://foojay.io/

<form autocomplete="off" role="search" method="get" action="https://foojay.io/">
  <div class="search-box__input-wrapper search-input-wrapper">
    <input id="searchInput" type="text" placeholder="Search..." value="" name="s">
    <label for="searchInput" class="search-input-wrapper__before-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="#fff" stroke-linejoin="round" xmlns:v="https://vecta.io/nano">
        <path d="M7.333 12.667c2.946 0 5.333-2.388 5.333-5.333S10.28 2 7.333 2 2 4.388 2 7.333s2.388 5.333 5.333 5.333z"></path>
        <path d="M14 14l-2.9-2.9" stroke-linecap="round"></path>
      </svg></label>
    <button type="button" class="search-input-wrapper__clear-btn" style="display: none;"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" opacity=".5" stroke="#fff" stroke-linecap="round" stroke-linejoin="round"
        xmlns:v="https://vecta.io/nano">
        <path d="M12 4L4 12"></path>
        <path d="M4 4l8 8"></path>
      </svg></button>
  </div>
</form>

POST https://foojay.io/wp-comments-post.php?wpe-comment-post=foojay

<form action="https://foojay.io/wp-comments-post.php?wpe-comment-post=foojay" method="post" id="commentform" class="comment-form">
  <p class="comment-notes"><span id="email-notes">Your email address will not be published.</span> <span class="required-field-message" aria-hidden="true">Required fields are marked <span class="required" aria-hidden="true">*</span></span></p>
  <div class="form-row">
    <label>
      <input placeholder="Email" type="email" id="email" name="email" value="" aria-describedby="email-notes">
    </label>
  </div>
  <div class="form-row">
    <label>
      <input placeholder="Name" type="text" id="author" name="author" value="">
    </label>
  </div>
  <div class="info"><span>Highlight your code snippets using [code lang="language name"] shortcode. Just insert your code between opening and closing tag: [code lang="java"] code [/code]. Or specify another language.</span></div>
  <div class="form-row">
    <label>
      <textarea placeholder="Comment" id="comment" name="comment" aria-required="true" required="required"></textarea>
    </label>
  </div>
  <div class="check__wrapper">
    <label class="check__label" for="wp-comment-cookies-consent">
      <input class="check__input" id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes">
      <span class="check__box"></span>
    </label>
    <p>Save my name, email, and website in this browser for the next time I comment.</p>
  </div>
  <p class="form-submit"><button name="submit" type="submit" id="submit" class="btn btn-green btn-submit">Post Comment</button> <input type="hidden" name="comment_post_ID" value="57573" id="comment_post_ID">
    <input type="hidden" name="comment_parent" id="comment_parent" value="0">
  </p>
  <p style="display: none;"><input type="hidden" id="akismet_comment_nonce" name="akismet_comment_nonce" value="3c4a5f6c23"></p>
  <p style="display: none !important;"><label>Δ<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_1" name="ak_js" value="1665016350452">
    <script>
      document.getElementById("ak_js_1").setAttribute("value", (new Date()).getTime());
    </script>
  </p>
</form>

GET https://foojay.io/

<form autocomplete="off" role="search" method="get" action="https://foojay.io/">
  <label>
    <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M9.16667 15.8333C12.8486 15.8333 15.8333 12.8486 15.8333 9.16667C15.8333 5.48477 12.8486 2.5 9.16667 2.5C5.48477 2.5 2.5 5.48477 2.5 9.16667C2.5 12.8486 5.48477 15.8333 9.16667 15.8333Z" stroke="white" stroke-width="2"
        stroke-linecap="round" stroke-linejoin="round"></path>
      <path d="M17.5 17.5L13.875 13.875" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
    </svg>
    <input placeholder="Search..." type="text" value="" name="s">
  </label>
</form>

Text Content

foojay.io Friends of OpenJDK
 * OpenJDK Hub
   * Releases
     OpenJDK Update & Release Details
      * Java 19
         * 19.0.0 – Sept, 2022
     
      * Java 18
         * 18.0.2 — July, 2022
         * 18.0.1 — April, 2022
         * 18.0.0 — March, 2022
     
      * Java 17
         * 17.0.4 — July, 2022
         * 17.0.3 — Apr, 2022
         * 17.0.2 — Jan, 2022
         * 17.0.1 — Oct, 2021
         * 17.0.0 — Sept, 2021
     
      * Java 15
        Java 15 Releases:
         * 15.0.8 — July, 2022
         * 15.0.7 — Apr, 2022
         * 15.0.6 — Jan, 2022
         * 15.0.5 — Oct, 2021
         * 15.0.4 — July, 2021
         * 15.0.3 — Apr, 2021
         * 15.0.2 — Jan, 2021
         * 15.0.1 — Oct, 2021
        
        View All
      * Java 13
        Java 13 Releases:
         * 13.0.12 — July, 2022
         * 13.0.11 — Apr, 2022
         * 13.0.10 — Jan, 2022
         * 13.0.9 — Oct, 2021
         * 13.0.8 — July, 2021
         * 13.0.7 — Apr, 2021
         * 13.0.6 — Jan, 2021
         * 13.0.5/13.0.5.1 — Oct, 2020
        
        View All
      * Java 11
        Java 11 Releases:
         * 11.0.16 — July, 2022
         * 11.0.15 — Apr, 2022
         * 11.0.14 — Jan, 2022
         * 11.0.13 — Oct, 2021
         * 11.0.12 — July, 2021
         * 11.0.11 — Apr, 2021
         * 11.0.10 — Jan, 2021
         * 11.0.9/11.0.9.1 — Oct, 2020
        
        View All
      * Java 8
        Java 8 Releases:
         * 8u342/345 — July, 2022
         * 8u332 — Apr, 2022
         * 8u322 — Jan, 2022
         * 8u312 — Oct, 2021
         * 8u302 — July, 2021
         * 8u292 — Apr, 2021
         * 8u282 — Jan, 2021
         * 8u272/8u275 — Oct, 2020
        
        View All
      * Java 7
        Java 7 Releases:
         * 7u351 — July, 2022
         * 7u342/7u341 — April, 2022
         * 7u332/7u331 — Jan, 2022
         * 7u251 — Jan, 2020
        
        View All
     
     
     
     
     View All
   * Distros
     Java Version Almanac
      * Long-Term Support (LTS):
        * Java 17
        * Java 11
        * Java 8
        * Java 7
      * Medium-Term Support (MTS):
        * Java 15
        * Java 13
      * Short-Term Support (STS):
        * Java 19
        * Java 18
        * Java 16
        * Java 14
        * Java 12
        * Java 10
        * Java 9
   
   * Command Line
     OpenJDK Command Line Arguments
      * Java 16
      * Java 15
      * Java 14
      * Java 13
      * Java 12
      * Java 11
      * Java 10
      * Java 9
      * Java 8
      * Java 7
      * Java 6
     
     
     
     
   * Terminology
     OpenJDK Terminology
      * OpenJDK with Visual C++
      * Thread Dump
      * OpenJDK Coding Guidelines and Code Reviews
      * Security and Vulnerability Management
      * jtreg Test Suites
      * Latency
      * Download
     
     
     
     
 * Community Hub
   * Foojay Today
     
      * Join Foojay on Slack
        
      * Demystifying JVM Memory Management
        May 20, 2021 Deepu K Sasidharan
      * VS Code: Getting Better and Better for Java
        May 18, 2021 Yaojin Yang
     
     
     
     
     View All
      * Latest
      * Opinion
      * testing
      * Tutorials
     
     Am I Testing the Right Way?
     David Schneider, Sebastian Konieczek
     October 04, 2022
     Read More
   * Java Events
     
     GIDS Live 2021
      * Virtual & Free
     
     April 27, 2021
     Virtual
     
     Tune in for Wurreka's second virtual conference and job event series, GIDS
     Live 2021, April 27-30. The four-day program includes an eclectic mix of
     technical talks, conversations and experiences, featuring some of the most
     talented and influential figures in software ...
   
   * Java User Groups
   * Java Champions
   * Slack Channel
 * About
   * About Foojay
   * Advisory Board
   * Download




Foojay Today
 * Java Core


USE PATTERN MATCHING TO SIMPLIFY JAVA

September 07, 2022

The concept of pattern matching has been around since the 1960s. It’s a
well-known language technique used in many programming languages, from Haskell
and AWK to Rust and Scala.

Pattern matching is relatively new to Java. It was introduced in JDK 14 and has
been progressing with new uses since then.

This article explores how these new features can make your code more concise
without losing readability.

If you’re more of an interactive learner, watch my on-demand webinar on pattern
matching in Java from June 2022. First, let’s back up and explain what pattern
matching is.


WHAT IS PATTERN MATCHING?

A pattern consists of two distinct things:

 * A match predicate gives us a way of determining whether we have a target that
   matches a given pattern. Being a predicate, it evaluates to a Boolean,
   meaning it matches against the pattern or it doesn’t.
 * One or more pattern variables is associated with that match predicate.
   Pattern variables are conditionally extracted based on the evaluation of the
   predicate.

There are several different pattern types that we can use.

 1. Constant: This has existed in Java from the beginning. The switch statement
    uses a constant pattern for each case. Since the pattern predicate matches a
    value, there is no need for a pattern variable.
 2. Type: Since Java is an object-oriented language, we can use a pattern
    predicate that matches a Java type. This is the pattern that we talk most
    about in this article.
 3. Deconstruction: In this type of pattern matching, not only do we evaluate a
    predicate, but we also extract values from objects to populate the pattern
    variables.
 4. Var: Like local variable type inference, introduced in JDK 10, this type of
    pattern matching uses the compiler to infer types for us.
 5. Any: Like var, it will match anything; but in this case, we simply ignore
    the value. This will become clear when we look at an example later.


WHY DO WE NEED PATTERN MATCHING?

Pattern matching allows us to test for a specific pattern on a character
sequence or a data structure. It makes code easier to read, easier to
understand, faster to create, and more resistant to bugs.

 * Pattern matching creates cleaner, shorter code by relying less on reflection
   and casting. Code expresses more complex logic with fewer lines.
 * Pattern matching reduces bugs caused by pattern dominance (pattern dominance
   is when a previous pattern supersedes another, making it unreachable) and
   pattern non-exhaustiveness (pattern exhaustiveness is when the compiler warns
   you that you have not checked for all possible variants of a type).


THE INSTANCEOF OPERATOR IN JDK 18

Let’s look at how we use the instanceof operator. Because Java is
object-oriented, we have polymorphism: we can view an object as any of the types
that it is – its exact type, any of the superclasses, and any of the interfaces
it implements.

Often, we are faced with a situation where we’re provided with a reference, but
we are unsure of its specific type. We can test the reference to see if it is a
given type using the instanceofoperator. Here’s a simple example:

if (o instanceof String) {
String s = (String)o;
System.out.printin("Length = " + s.length());
}
if (o instanceof String) { String s = (String)o; System.out.printin("Length = "
+ s.length()); }


if (o instanceof String) {
  String s = (String)o;
  System.out.printin("Length = " + s.length());
}

Having determined that the reference o is of type String, we must define a new
local variable of type Stringand assign to it the value of o using an explicit
cast. Pattern matching for instanceof, a permanent feature since JDK 16,
eliminates this unnecessary extra boilerplate code.

The code now looks like this:

if (o instanceof String s) {
System.out.printin("Length = " + s.length());
}
if (o instanceof String s) { System.out.printin("Length = " + s.length()); }


if (o instanceof String s) {
  System.out.printin("Length = " + s.length());
}

Here, the pattern predicate is whether o is an instanceof String and the pattern
variable is s, which is assigned for us by the compiler.

Pattern matching for instanceof uses what is called flow scoping. If you look at
local variables, their scope runs from where it is declared until the end of the
block in which it is declared (method, loop, block, etc.)  They are also subject
to definite assignment (they must explicitly be assigned a value). In the case
of predicate variables, they are also subject to definite assignment, but their
scope is the set of places where they would have definite assignment.

Taking the example above, the scope of s is only valid inside the true branch of
this if statement because that’s the only place it will have definite
assignment. There are two things to bear in mind here.

1 – If you invert the test like this, the variable s will have scope until the
end of the block containing the if statement:

if (!(o instanceof String s)) return;
if (!(o instanceof String s)) return;


if (!(o instanceof String s))  return;

2 – This allows the reuse of the same variable name, like this:

if (o instanceof Float n) {
} else if (o instanceof Integer n) {
} else if (o instanceof Short n) {
}
if (o instanceof Float n) { } else if (o instanceof Integer n) { } else if (o
instanceof Short n) { }


if (o instanceof Float n) {
  } else if (o instanceof Integer n) {
  } else if (o instanceof Short n) {
}


SWITCH STATEMENTS AND EXPRESSIONS IN JDK 18

The next use of pattern matching in Java is in switch. Until JDK 17, even with
the introduction of switch expressions, we were still constrained to a small set
of types we could switch over: integral values, strings, and enumerations. JDK
17 introduced pattern matching for switch, which allows us to use a type pattern
as a case.

For example:

void typeTester(Object o) {
switch (o) {
case null -> System.out.printIn("Null type");
case String s -> System.out.printIn("String length: " + s.length());
case Color c -> System.out.printIn("Color with RGB: " + c.getRGB();
case int[] ia -> System.out.printIn("Array of ints, length" + ia.length);
default -> System.out.printIn(o.toString());
}
}
void typeTester(Object o) { switch (o) { case null -> System.out.printIn("Null
type"); case String s -> System.out.printIn("String length: " + s.length());
case Color c -> System.out.printIn("Color with RGB: " + c.getRGB(); case int[]
ia -> System.out.printIn("Array of ints, length" + ia.length); default ->
System.out.printIn(o.toString()); } }


void typeTester(Object o) {
    switch (o) {
        case null -> System.out.printIn("Null type");
        case String s -> System.out.printIn("String length: " + s.length());
        case Color c -> System.out.printIn("Color with RGB: " + c.getRGB();
        case int[] ia -> System.out.printIn("Array of ints, length" + ia.length);
        default -> System.out.printIn(o.toString());
    }
}


There are several things to understand here.

Both switch statements and switch expressions can now include an explicit null
case. This is useful to eliminate the need for a potential explicit test before
the switch. To maintain backwards compatibility, if a null case is not included,
the compiler will insert one as the first that throws a NullPointerException.
Since a null is always a null, there is no need for a pattern variable. It is
also possible to include null with the default case:

null, default -> System.out.printIn("Invalid type");
null, default -> System.out.printIn("Invalid type");


null, default -> System.out.printIn("Invalid type");

For the String and Color type cases, the pattern predicate matches on those
types and assigns the reference to the specified pattern variable if there is a
match. The scope of the pattern variables is only in the relevant case block

Primitives (like int and float) in Java are not types, so we cannot use them for
a pattern predicate. However, an array of primitives is a type and we can
therefore have a case for an array of ints.

When using pattern matching for switch (either in a statement or expression),
the switch must be exhaustive. This means that all possible types must be
handled.

Let’s take this switch, for example.

switch (o) {
case integer i -> System.out.printIn("Integer");
case Byte b -> System.out.printIn("Byte");
}
switch (o) { case integer i -> System.out.printIn("Integer"); case Byte b ->
System.out.printIn("Byte"); }


switch (o) {
  case integer i -> System.out.printIn("Integer");
  case Byte b -> System.out.printIn("Byte");
}

In this case, if o is of type Float, there is no case to handle it. We could
have simply passed over the switch, but that could lead to hard-to-find bugs and
is not a good design.

The obvious way to resolve this is to include a default case that matches
against anything that is not an Integer or Byte. This does not mean, however,
that every switch must have a default case to be complete.

JDK 15 introduced another new language construct, sealed classes. Here we define
a simple sealed type.

Public sealed class Shape permits Triangle, Square, Pentagon {...}
Public sealed class Shape permits Triangle, Square, Pentagon {...}


Public sealed class Shape permits Triangle, Square, Pentagon {...}

We could use this in a switch like this:

void typeTester(Shape shape) {
switch (shape) {
case Triangle t -> System.out.println("It's a triangle");
case Square s -> System.out.println("It's a square");
case Pentagon p -> System.out.println("It's a pentagon");
case Shape s -> System.out.println("It's a shape");
}
}
void typeTester(Shape shape) { switch (shape) { case Triangle t ->
System.out.println("It's a triangle"); case Square s -> System.out.println("It's
a square"); case Pentagon p -> System.out.println("It's a pentagon"); case Shape
s -> System.out.println("It's a shape"); } }


void typeTester(Shape shape) {
  switch (shape) {
    case Triangle t -> System.out.println("It's a triangle");
    case Square s -> System.out.println("It's a square");
    case Pentagon p -> System.out.println("It's a pentagon");
    case Shape s -> System.out.println("It's a shape");
  }
}

Since Shape can only have subclasses of Triangle, Square and Pentagon, we have
covered all possibilities in the switch, and it is exhaustive (this is also
referred to as completeness).

The order of the patterns is also significant. If we were to make the case for
Shape the first one, it would catch all objects. Since this would render the
lower cases unreachable, the compiler would generate an error.

Pattern matching for switch also includes guarded patterns. In this case, we can
add a test to our pattern. Using the above example:

void typeTester(Shape shape) {
switch (shape) {
case Triangle t && t.size() < 25 -> System.out.println("Small triangle");
case Triangle t -> System.out.println("Big triangle");
case Square s -> System.out.println("It's a square");
case Pentagon p -> System.out.println("It's a pentagon");
case Shape s -> System.out.println("It's a shape");
}
}
void typeTester(Shape shape) { switch (shape) { case Triangle t && t.size() < 25
-> System.out.println("Small triangle"); case Triangle t ->
System.out.println("Big triangle"); case Square s -> System.out.println("It's a
square"); case Pentagon p -> System.out.println("It's a pentagon"); case Shape s
-> System.out.println("It's a shape"); } }


void typeTester(Shape shape) {
  switch (shape) {
    case Triangle t && t.size() < 25 -> System.out.println("Small triangle");
    case Triangle t -> System.out.println("Big triangle");
    case Square s -> System.out.println("It's a square");
    case Pentagon p -> System.out.println("It's a pentagon");
    case Shape s -> System.out.println("It's a shape");
  }
}

The first case for Triangle now includes an additional test (guard) to determine
if its size is less than 25. For the switch to remain exhaustive, we must also
have a case for Triangle without a guard to handle triangles of size 25 or
greater.

In JDK 19, the syntax for guarded patterns will change, replacing the &&
operator with the keyword, when. Similarly, we must put the guarded Triangle
case before the unguarded to avoid the guarded one being unreachable.

More pattern matching will be added to Java in the future. Already, JDK 19 is
scheduled to include pattern matching for records, which is a deconstruction
pattern. We’ll cover that and some other aspects in a later blog post.


ALL THE READABILITY WITHOUT THE UNNECESSARY CODE

As you can see, pattern matching is a powerful addition to the Java language
that reduces the amount of boilerplate code required without sacrificing
readability.

It also provides several ways to help detect errors at compile time rather than
at runtime when your code is in production.

Why not try using pattern matching in your next Java application?

Want to learn more about pattern matching in JDK 18? Watch our on-demand webinar
from June 2022, The Art of Java Language Pattern Matching.

You will learn some of the newer features in the Java language, plus some ideas
that may be included in future versions of Java, all around this idea of pattern

Don’t Forget to Share This Post!
 * 
 * 
 * 

 * Author Simon Ritter


RELATED ARTICLES

View All
 * JDK 7: An Extended Hello and Farewell
   
   Azul continues to provide updates (scheduled quarterly ones and any
   out-of-bounds) to the Zulu builds of OpenJDK 7 until at least December 2027.
   
   Read More
    * Developer Tools
    * Getting Started
    * Java Core
   
    * Simon Ritter
   
   Jul 12, 2022
 * Are Java Security Updates Important?
   
   Recently, I was in discussion with a Java user at a bank about the
   possibilities of using Azul Platform Core to run a range of applications. 
   
   Security is a very serious concern when sensitive data is in use, and
   potentially huge sums of money could be stolen.
   
   I was, therefore, somewhat taken aback when the user said, “We’re not worried
   about installing Java updates as our core banking services are behind a
   firewall.”
   
   Read More
    * Security
   
    * Simon Ritter
   
   Aug 03, 2021
 * Much Ado About Nothing in Java
   
   Occasionally something in Java pops up that I thought I knew about, but it
   turns out I didn’t appreciate all the subtle details.
   
   This was recently the case for “nul”. Before I started using Java, the main
   programming language I used was C.  This was great for things like operating
   systems and device drivers because it uses explicit pointers. References to
   data are through a numerical address that can be manipulated if required.
   
   Although null might seem like a simple, straightforward concept, there are
   some edge cases that make its use require a little more thought. I hope this
   provides you with a better understanding of nothing (null).
   
   Read More
    * Getting Started
   
    * Simon Ritter
   
   Feb 23, 2021


AUTHOR(S)

 * Simon Ritter
    * 
    * 
   
   Deputy CTO at Azul Systems


COMMENTS (1)

Leave a Comment


CANCEL REPLY

Your email address will not be published. Required fields are marked *



Highlight your code snippets using [code lang="language name"] shortcode. Just
insert your code between opening and closing tag: [code lang="java"] code
[/code]. Or specify another language.


Save my name, email, and website in this browser for the next time I comment.

Post Comment



Δ

Java Annotated Month-to-month – October 2022 - LunaticTech

[…] Use Pattern Matching to Simplify Java – If you happen to’re on the lookout
for a easy rationalization of Sample Matching, then this piece is for you! It
exhibits how you need to use Sample Matching to make your code concise with out
shedding readability, and why it pays to take action. […]

7:44 pm, October 3, 2022
foojay.io Friends of OpenJDK


OPENJDK HUB

 * Releases
 * Distros
 * Command Line


COMMUNITY HUB

 * Foojay Today
 * Events Calendar


ABOUT

 * About Us
 * Advisory Board


 * hello@foojay.io
 * Sitemap
 * Terms of Use





SET EVENT REMINDER

 * Microsoft Outlook
 * Google Calendar
 * macOS Calendar

SUBSCRIBE TO FOOJAY UPDATES:

https://foojay.io/feed/
Copied to the clipboard


By clicking “Accept All Cookies”, you agree to the storing of cookies on your
device to enhance site navigation, analyze site usage, and assist in our
marketing efforts. View Cookie Policy

Cookies Settings Reject All Accept All Cookies



PRIVACY PREFERENCE CENTER




 * YOUR PRIVACY


 * FUNCTIONAL COOKIES


 * TARGETING COOKIES


 * PERFORMANCE COOKIES


 * STRICTLY NECESSARY COOKIES

YOUR PRIVACY

When you visit any website, it may store or retrieve information on your
browser, mostly in the form of cookies. This information might be about you,
your preferences or your device and is mostly used to make the site work as you
expect it to. The information does not usually directly identify you, but it can
give you a more personalized web experience. Because we respect your right to
privacy, you can choose not to allow some types of cookies. Click on the
different category headings to find out more and change our default settings.
However, blocking some types of cookies may impact your experience of the site
and the services we are able to offer.

FUNCTIONAL COOKIES

Functional Cookies


These cookies enable the website to provide enhanced functionality and
personalisation. They may be set by us or by third party providers whose
services we have added to our pages. If you do not allow these cookies then some
or all of these services may not function properly.

TARGETING COOKIES

Targeting Cookies


These cookies may be set through our site by our advertising partners. They may
be used by those companies to build a profile of your interests and show you
relevant adverts on other sites. They do not store directly personal
information, but are based on uniquely identifying your browser and internet
device. If you do not allow these cookies, you will experience less targeted
advertising.

PERFORMANCE COOKIES

Performance Cookies


These cookies allow us to count visits and traffic sources so we can measure and
improve the performance of our site. They help us to know which pages are the
most and least popular and see how visitors move around the site. All
information these cookies collect is aggregated and therefore anonymous. If you
do not allow these cookies we will not know when you have visited our site, and
will not be able to monitor its performance.

STRICTLY NECESSARY COOKIES

Always Active

These cookies are necessary for the website to function and cannot be switched
off in our systems. They are usually only set in response to actions made by you
which amount to a request for services, such as setting your privacy
preferences, logging in or filling in forms. You can set your browser to block
or alert you about these cookies, but some parts of the site will not then work.
These cookies do not store any personally identifiable information.

Back Button


BACK

Filter Button
Consent Leg.Interest
checkbox label label
checkbox label label
checkbox label label

Clear
checkbox label label
Apply Cancel
Confirm My Choices
Reject All Allow All



PRIVACY PREFERENCE CENTER




 * YOUR PRIVACY


 * FUNCTIONAL COOKIES


 * TARGETING COOKIES


 * PERFORMANCE COOKIES


 * STRICTLY NECESSARY COOKIES

YOUR PRIVACY

When you visit any website, it may store or retrieve information on your
browser, mostly in the form of cookies. This information might be about you,
your preferences or your device and is mostly used to make the site work as you
expect it to. The information does not usually directly identify you, but it can
give you a more personalized web experience. Because we respect your right to
privacy, you can choose not to allow some types of cookies. Click on the
different category headings to find out more and change our default settings.
However, blocking some types of cookies may impact your experience of the site
and the services we are able to offer.

FUNCTIONAL COOKIES

Functional Cookies


These cookies enable the website to provide enhanced functionality and
personalisation. They may be set by us or by third party providers whose
services we have added to our pages. If you do not allow these cookies then some
or all of these services may not function properly.

TARGETING COOKIES

Targeting Cookies


These cookies may be set through our site by our advertising partners. They may
be used by those companies to build a profile of your interests and show you
relevant adverts on other sites. They do not store directly personal
information, but are based on uniquely identifying your browser and internet
device. If you do not allow these cookies, you will experience less targeted
advertising.

PERFORMANCE COOKIES

Performance Cookies


These cookies allow us to count visits and traffic sources so we can measure and
improve the performance of our site. They help us to know which pages are the
most and least popular and see how visitors move around the site. All
information these cookies collect is aggregated and therefore anonymous. If you
do not allow these cookies we will not know when you have visited our site, and
will not be able to monitor its performance.

STRICTLY NECESSARY COOKIES

Always Active

These cookies are necessary for the website to function and cannot be switched
off in our systems. They are usually only set in response to actions made by you
which amount to a request for services, such as setting your privacy
preferences, logging in or filling in forms. You can set your browser to block
or alert you about these cookies, but some parts of the site will not then work.
These cookies do not store any personally identifiable information.

Back Button


BACK

Filter Button
Consent Leg.Interest
checkbox label label
checkbox label label
checkbox label label

Clear
checkbox label label
Apply Cancel
Confirm My Choices
Reject All Allow All